0 00:00:00,000 --> 00:00:06,000 Translated by visionNoob, KNU https://github.com/insurgent92/CS231N_17_KOR_SUB 1 00:00:07,961 --> 00:00:12,153 잘 들리시나요? 좋습니다. 잠시 지연이 있었습니다. 2 00:00:12,153 --> 00:00:24,081 잠시 기술적인 문제가 있었습니다. 3 00:00:25,353 --> 00:00:30,420 오늘은 10강입니다. Recurrent Neural Networks(RNN)에 대해 배워보겠습니다. 4 00:00:30,420 --> 00:00:33,003 그 전에 공지사항을 전달하겠습니다. 5 00:00:33,003 --> 00:00:37,353 현재 과제1을 채점 중에 있습니다. 6 00:00:37,353 --> 00:00:46,251 최종 성적이 아마도 오늘 발표될 예정입니다. 과제2 deadline 전에는 과제1 성적이 나왔으면 좋겠네요 7 00:00:46,251 --> 00:00:50,361 과제2의 제출기한은 금일 11:59 p.m. 까지입니다. 8 00:00:50,361 --> 00:00:56,633 과제 2를 다 마치신 분 있으신가요? 절반정도 되는군요 9 00:00:56,633 --> 00:01:03,811 제가 예전에 과제2는 상당히 오래걸릴 수 있으니 미리 시작하는 것이 좋다고 말씀드렸습니다. 10 00:01:03,811 --> 00:01:06,561 late dates가 남아있길 바랍니다. 11 00:01:06,561 --> 00:01:10,531 화요일 수업시간에는 중간고사가 있습니다. 12 00:01:10,531 --> 00:01:15,881 아마 강의실이 비좁아서 모두 시험을 치룰 수 없을 것입니다. 13 00:01:15,881 --> 00:01:20,062 따라서 다른 강의실들도 함께 빌려서 진행할 예정입니다. 14 00:01:20,062 --> 00:01:26,099 향후 세부사항은 다시한번 공지하겠습니다. 15 00:01:26,099 --> 00:01:28,179 또 한가지 공지사항이 있습니다. 16 00:01:28,179 --> 00:01:34,950 현재 Train Game 이라는 사이트를 개설하고있습니다. Train Game은 웹 브라우저 기반이며 17 00:01:34,950 --> 00:01:39,927 여러분 누구나 접속해서 딥러닝 모델을 학습시키고 학습 도중 하이퍼파라미터를 조정하실 수 있습니다. 18 00:01:39,927 --> 00:01:47,646 앞서 강의들에서 배웠던 다양한 하이퍼파라미터들을 손으로 직접 만져볼 수 있는 아주 좋은 툴입니다. 19 00:01:47,646 --> 00:01:53,190 Train Game를 무조건 하실 필요는 없습니다. 하지만, Train Game는 실제로 다양한 데이터를 다뤄보며 20 00:01:53,190 --> 00:01:57,481 데이터 타입에 따라 하이퍼파라미터가 어떤 영향을 미치는지에 직관을 얻을 수 있는 아주 좋은 기회가 될것입니다. 21 00:01:57,481 --> 00:02:05,790 현재 몇 가지 버그를 수정하고 있습니다. 조만간 여러분에게 사용법과 함께 공개하도록 하겠습니다. 22 00:02:05,790 --> 00:02:11,008 다시한번 말씀드리지만, 필수는 아닙니다. 하지만 해보시면 도움이 많이 될 것입니다. 23 00:02:11,008 --> 00:02:17,204 Train Game을 써보신 분들에게는 Extra credit을 지급할 예정입니다. 24 00:02:18,208 --> 00:02:23,458 아무튼 버그만 다 잡으면 다시 한번 공지드리겠습니다. 25 00:02:24,720 --> 00:02:28,139 지난 강의 복습을 해봅시다. CNN 아키텍쳐들을 배웠습니다. 26 00:02:28,139 --> 00:02:35,006 ImageNet Classification Challenge를 중심으로 연대순 우승자들을 알아봤습니다. 27 00:02:35,006 --> 00:02:41,331 2012년에는 AlexNet이 있었습니다. 9-layer CNN인데, 아주 잘 동작했습니다. 28 00:02:41,331 --> 00:02:48,081 AlexNet이 Computer Vision의 진화를 촉발시켰으며 딥러닝 시대의 서막을 열었습니다. 29 00:02:48,081 --> 00:02:56,699 2014년으로 넘어가봅시다. 이전의 모델들보다 훨씬 더 깊어진 두 모델이 있었습니다. VGG와 GoogLeNet 입니다. 30 00:02:56,699 --> 00:03:02,930 VGGNet은 16/19 레이어를, GoogLeNet은 22 레이어를 가진 모델이었습니다. 31 00:03:02,930 --> 00:03:11,230 2014년 모델들에서 흥미로운 점은 2014년에는 Batch normalization 이 발명되기 이전이라는 점입니다. 32 00:03:11,230 --> 00:03:18,761 Batch Norm이 없던 시절이라서 레이어가 깊을 모델을 학습시키는 일은 상당히 어려웠습습니다. 33 00:03:18,761 --> 00:03:24,869 이 두 모델은 깊은 모델을 수렴시키기 위해서 각종 테크닉(hackery)을 써야했습니다. 34 00:03:24,869 --> 00:03:28,579 가령 VGGNet는 16/19 레이어가 있습니다. 35 00:03:28,579 --> 00:03:34,107 하지만 처음에는 11레이어 모델을 학습시켰습니다. 11 레이어가 모델이 잘 수렴하는 한계였습니다. 36 00:03:34,107 --> 00:03:40,059 그리고 나서 11레이어 중간에 레이어를 무작위로 추가해서 VGG-16, VGG-19 를 학습시킨 것이죠 37 00:03:40,059 --> 00:03:46,539 이렇게, Bath norm이 없던 2014년에는 학습 자체가 상당히 어려운 문제였습니다. 38 00:03:46,539 --> 00:03:52,539 유사한 사례로 GoogLeNet의 경우에는 auxiliary classifiers를 도입했습니다. 39 00:03:52,539 --> 00:03:56,539 auxiliary classifiers는 classification 성능을 올리기 위해서 도입된 것이 아닙니다. 40 00:03:56,539 --> 00:04:03,430 단지 네트워크의 초기 레이어에 gradient를 직접 흘려보내기 위한 수단이었습니다. 41 00:04:03,430 --> 00:04:10,411 GoogLeNet은 Batch Norm 이전에 이런 테크닉을 사용했습니다. 42 00:04:10,411 --> 00:04:17,321 하지만 Batch Norm이 있다면 굳이 이런 식의 테크닉은 더이상 필요하지 않습니다. 43 00:04:17,321 --> 00:04:24,350 2015년에는 ResNet이라는 아주 멋드러진 모델이 있었습니다. 44 00:04:24,350 --> 00:04:28,310 ResNet은 shortcut connection과 residual block이 도입된 모델입니다. 45 00:04:28,310 --> 00:04:39,110 ResNet에서는 레이어의 출력은 입력 + residual block의 출력 입니다. 46 00:04:39,110 --> 00:04:43,308 아주 흥미로운 구조입니다. 이 구조는 두 가지 아주 좋은 속성을 지니고 있습니다. 47 00:04:43,308 --> 00:04:49,531 하나는, 우선 residual block의 가중치가 0이면 이 block은 indentity mapping 을 합니다. 48 00:04:49,531 --> 00:04:55,681 이 속성은, 모델이 '필요없는 레이어" 를 사용하지 않도록 학습하는데 아주 유용합니다. 49 00:04:55,681 --> 00:05:02,171 그리고 ResNet의 관점에서 L2 Regularization을 해석해 볼 수도 있습니다. 50 00:05:02,171 --> 00:05:08,321 레이어에 L2 Regularization을 추가시키면 L2는 모든 파라미터가 0이 되도록 노력할 것입니다. 51 00:05:08,321 --> 00:05:12,739 사실 기본적인 CNN 아키텍쳐의 관점에서보면 모든 파라미터가 0이면 이상합니다. 52 00:05:12,739 --> 00:05:20,510 하지만 ResNet의 관점에서는 파라미터를 0으로 만드려는 속성은 모델이 불필요한 레이어를 사용하지 않도록 해줄 수 있습니다. 53 00:05:20,510 --> 00:05:26,310 파라미터들을 계속 0으로 보내면 residual block이 identity가 되기 떄문이죠. 54 00:05:26,310 --> 00:05:31,371 ResNet의 또 한가지 특성은 backward pass 에서의 gradient flow와 관련있습니다. 55 00:05:31,371 --> 00:05:34,361 "Addition gates (+)" 가 backward pass에 어떤 영향을 미칠지 생각해보면 56 00:05:34,361 --> 00:05:39,881 Upstream gradient 가 "Addition gate" 를 만나면 두 갈래로 나눠지게 됩니다. 57 00:05:39,881 --> 00:05:46,361 Upstream gradient가 오면 convolution block 으로도 흘러들어가지만 58 00:05:46,361 --> 00:05:50,811 residual connection 덕분에 현재 레이어를 생략하고 직접 이전 레이어로 흘러갈 수도 있습니다. 59 00:05:50,811 --> 00:05:59,150 Residual blocks을 수백 레이어 쌓아올린 네트워크가 있다고 해봅시다. 60 00:05:59,150 --> 00:06:05,561 Residual connection은 gradient를 위한 일종의 고속도로 역할을 합니다. gradient를 원활하게 전달하기 위해서죠 61 00:06:05,561 --> 00:06:09,630 이런 특성으로 학습을 더 쉽고 빠르게 할 수 있습니다. 62 00:06:09,630 --> 00:06:15,738 그리고 이런 특성은 모델이 엄청 깊더라도 잘 수렴할 수 있도록 도와줍니다. 63 00:06:15,738 --> 00:06:21,550 모델의 gradient flow를 잘 다루는 것은 Machine learning 전 분야에 걸쳐서도 아주 중요합니다. 64 00:06:21,550 --> 00:06:28,564 RNN에서도 아주 중요하죠. 따라서 gradient flow는 오늘 강의의 후반부에 다시한번 다루겠습니다. 65 00:06:31,148 --> 00:06:38,068 지난 시간에 DensNet, FractalNet 과 같은 이색적인 CNN 아키텍쳐도 살펴보았습니다. 66 00:06:38,068 --> 00:06:43,070 이 모델들은 gradient flow의 관점에서 아주 잘 해석해 볼 수 있습니다. 67 00:06:43,070 --> 00:06:48,619 DenseNet이나 FractalNet 같은 모델들은 모델 내부에 additional shortcut (identity)를 추가합니다. 68 00:06:48,619 --> 00:07:00,571 이 모델들은 Loss와 각 Layer를 직접 연결하기 때문에 backward pass가 아주 수월합니다. 69 00:07:00,571 --> 00:07:09,760 CNN 아키텍쳐에서 Gradient Flow를 잘 다루려는 시도는 최근 몇 년간 아주 활발하게 이루어졌습니다. 70 00:07:09,760 --> 00:07:15,221 앞으로도 신기한 아카텍쳐들이 많이 나올 것 같습니다. 71 00:07:16,257 --> 00:07:24,331 지난 강의에서 보셨던 그래프입니다. 모델 별 연산량, 크기 등을 비교해 보았습니다. 72 00:07:24,331 --> 00:07:27,971 이 그래프를 유심히 살펴보면 아주 재미있는 속성이 있습니다. 73 00:07:27,971 --> 00:07:32,801 AlexNet와 VGGNet는 파라미터가 엄청 많습니다. 74 00:07:32,801 --> 00:07:37,119 사실 파라미터가 많은 이유는 전적으로 FC-layer 때문입니다. 75 00:07:37,119 --> 00:07:39,959 가령 AlexNet의 경우에는 대략 64M 개의 파라미터가 있습니다. 76 00:07:39,959 --> 00:07:47,771 AlexNet의 FC-Layer를 살펴봅시다. FC-Layers의 입력은 마지막 Conv output 6 x 6 x 256 입니다. 77 00:07:47,771 --> 00:07:51,190 이 값(256 x 6 x 6) 들이 4096 개의 FC-layer 노드와 연결됩니다. 78 00:07:51,190 --> 00:07:56,851 이 부분의 가중치 매트릭스는 엄청나게 큽니다. 79 00:07:56,851 --> 00:08:01,921 매트릭스의 크기는 6x6x256x4096 이 되겠죠 80 00:08:01,921 --> 00:08:06,370 이 레이어 하나에만 38m개의 파라미터가 있습니다. 81 00:08:06,370 --> 00:08:11,859 AlexNet의 전체 파라미터 중 절반 이상이 FC-Layer에 집중되어 있습니다. 82 00:08:11,859 --> 00:08:24,241 AlexNet의 FC-Layer 의 파라미터 갯수를 다 더해보면 FC-Layer에서만 62M 가량의 파라미터가 있다는 것을 알 수 있습니다. 83 00:08:24,241 --> 00:08:31,110 GoogLeNet 이나 ResNet 같은 아키텍쳐들은 FC-Layer를 상당부분 걷어냈습니다. 84 00:08:31,110 --> 00:08:33,698 FC-Layer를 Global Average Pooling (GAP) 으로 대체시킵니다. 85 00:08:33,698 --> 00:08:40,935 GAP를 사용하게 되면서 파라미터 갯수를 상당히 감소시켰습니다. 86 00:08:44,463 --> 00:08:49,604 지금까지는 CNN 아키텍쳐를 복습해보았습니다. 87 00:08:49,604 --> 00:08:56,321 이제부터는 Recurrent Neural Network에 대해서 배워보도록 하겠습니다. 88 00:08:56,321 --> 00:09:03,222 지금까지 배운 아키텍쳐들은(Vanilla Neural Network) 다음과 같은 모양이하고 할 수 있습니다. 89 00:09:03,222 --> 00:09:08,593 네트워크는 이미지 또는 벡터를 입력으로 받습니다. 90 00:09:08,593 --> 00:09:13,850 입력 하나가 Hidden layer를 거쳐서 하나의 출력을 내보냅니다. 91 00:09:13,850 --> 00:09:18,876 Classification 문제라면 카테고리가 되겠군요 92 00:09:20,071 --> 00:09:25,942 하지만 Machine Learning의 관점에서 생각해보면 모델이 다양한 입력을 처리할 수 있도록 유연해질 필요가 있습니다. 93 00:09:25,942 --> 00:09:35,313 그런 관점에서 RNN은 네트워크가 다양한 입/출력을 다룰 수 있는 여지를 제공해줍니다. 94 00:09:35,313 --> 00:09:41,009 RNN 구조를 이용할 때, 가령 "one to many" 모델은 95 00:09:41,009 --> 00:09:48,721 입력은 이미지와 같은 "단일 입력" 이지만 출력은 caption 과 같은 "가변 출력" 입니다. 96 00:09:48,721 --> 00:09:54,081 caption에 따라서 단어의 수가 천차 만별이겠죠 따라서 출력은 가변 출력입니다. 97 00:09:54,081 --> 00:09:56,491 "many to one" 모델도 있습니다. 98 00:09:56,491 --> 00:10:01,001 이제는 입력이 "가변 입력" 입니다. 가령 문장이 될 수 있겠군요 99 00:10:01,001 --> 00:10:06,161 그리고 이 문장의 "감정"을 분류하는 것입니다. 부정적/긍적적인 문장인지를 구별하는 것이죠 100 00:10:06,161 --> 00:10:12,512 그리고 Computer Vision Task의 경우에는, 가령 입력이 비디오라고 해봅시다. 비디오에 따라 전체 프레임 수가 다양합니다. 101 00:10:12,512 --> 00:10:16,401 전체 비디오를 읽으려면 가변 길이의 입력을 받아야 합니다. 102 00:10:16,401 --> 00:10:22,721 비디오를 입력으로 받아서, 비디오에 나타나는 activity 또는 action을 분류하는 문제를 생각해봅시다. 103 00:10:22,721 --> 00:10:29,931 이 경우에는 입/출력 모두 가변이어야 합니다. 104 00:10:29,931 --> 00:10:37,302 또는 Machine translation의 예를 볼 수도 있습니다. 입력은 English sentence 입니다. 가변 입력이죠 105 00:10:37,302 --> 00:10:41,633 그리고 출력은 번역 결과인 "Fench sentence" 입니다. 출력 또한 가변 출력인 것입니다. 106 00:10:41,633 --> 00:10:46,801 그리고 English Sentence의 길이는 변역된 French Sentence의 길이와 다를 것입니다. 107 00:10:46,801 --> 00:10:53,931 이 경우에는 가변 입/출력이 가능한 모델이 필요합니다. 108 00:10:53,931 --> 00:11:04,771 마지막으로, 입력은 비디오와 같은 가변 입력이고 각 프레임마다 출력 값이 나와야 하는 상황을 생각해 볼 수 있습니다. 109 00:11:04,771 --> 00:11:11,891 가령 비디오가 입력이고 매 프레임마다 classification을 해야 하는 상황일 수 있습니다. 110 00:11:11,891 --> 00:11:17,401 Recurrent Neural Networks는 가변 길이의 데이터를 다루기 위해 필요한 일반적인 방법(paradigm) 입니다. 111 00:11:17,401 --> 00:11:23,469 RNN은 앞서 말씀드린 다양한 상황들을 모델이 잘 처리할 수 있도록 줍니다. 112 00:11:24,349 --> 00:11:33,752 그리고 고정 길이의 입/출력이 필요한 상황에서도 RNN은 상당히 중요합니다. 여전히 유용하죠. 113 00:11:33,752 --> 00:11:38,793 입/출력은 고정이지만 sequential processing가 요구되는 경우입니다. 114 00:11:38,793 --> 00:11:46,227 가령 여기 이미지가 있습니다. 고정 입력이죠 그리고 이미지의 숫자가 몇 인지 분류하는 문제입니다. 115 00:11:46,227 --> 00:11:50,393 입력 이미지의 정답을 feed forward pass 한 번만 가지고 결정하는 것이 아니라 116 00:11:50,393 --> 00:11:55,553 이 네트워크는 이미지의 여러 부분은 조금씩 살펴봅니다. 117 00:11:55,553 --> 00:12:01,742 이미지를 살펴 본 후에 숫자가 몇 인지를 최종적으로 판단합니다. 118 00:12:01,742 --> 00:12:17,473 이 예제 처럼 입/출력이 고정된 길이라고 해도 "가변 과정(processing)" 인 경우에 RNN은 상당이 유용합니다. 119 00:12:17,473 --> 00:12:23,923 제가 상당히 좋아하는 논문입니다. 동일한 방법으로 "이미지를 생성" 을 제안하기도 합니다. 120 00:12:23,923 --> 00:12:29,723 자 이제는 모델은 Train time에서 본 이미지들을 바탕으로 새로운 이미지를 생성해 냅니다. 121 00:12:29,723 --> 00:12:36,254 이를 위해 RNN을 이용할 수 있습니다. 순차적으로 전체 출력의 일부분씩 생성해 내는 것입니다. 122 00:12:36,254 --> 00:12:46,380 이 경우에도 전체 출력은 고정된 길이지만, RNN을 이용해서 일부분씩 순차적으로 처리할 수 있습니다. 123 00:12:46,380 --> 00:12:51,662 RNN을 이런 경우에도 사용될 수 있는 것이죠. 124 00:12:51,662 --> 00:12:58,785 RNN을 활용할 수 있는 다양한 예시들을 살펴보았습니다. 그렇다면 도대체 어떻게 동작하는 것일까요? 125 00:12:58,785 --> 00:13:04,163 일반적으로 RNN은 작은 "Recurrent Core Cell" 을 가지고 있습니다. 126 00:13:04,163 --> 00:13:11,382 입력 x가 RNN으로 들어갑니다. RNN에는 내부에 "hidden state" 를 가지고있습니다. 127 00:13:11,382 --> 00:13:17,641 "hidden state"는 RNN이 새로운 입력을 불러들일 때마다 매번 업데이트됩니다. 128 00:13:17,641 --> 00:13:23,980 "hidden state"는 모델에 feed back되고 이후에 또 다시 새로운 입력 x가 들어옵니다. 129 00:13:23,980 --> 00:13:28,822 RNN이 매 단계마다 값을 출력하는 경우를 생각해 봅시다. 130 00:13:28,822 --> 00:13:31,043 그러면 이런 식으로 진행이 됩니다. 1. RNN이 입력을 받습니다. 131 00:13:31,043 --> 00:13:34,469 2. "hidden state"를 업데이트합니다. 3. 출력 값을 내보냅니다. 132 00:13:35,814 --> 00:13:40,961 그렇다면 RNN 구조를 수식적으로 표현하면 어떨까요? 133 00:13:40,961 --> 00:13:46,443 오른쪽 그림의 초록색 RNN block은 "재귀적인 관계"를 연산할 수 있도록 설계됩니다. "함수 f" 로 말이죠 134 00:13:46,443 --> 00:13:49,094 파라미터 W를 가진 함수 f가 있습니다. 135 00:13:49,094 --> 00:13:55,374 함수 f는 "이전 상태의 hidden state인 h_t-1" 과 "현재 상태의 입력인 x_t" 를 입력으로 받습니다. 136 00:13:55,374 --> 00:14:01,420 그리고 h_t를 출력합니다. h_t는 "다음 상태의 hidden state" 입니다.(updated hidden state) 137 00:14:01,420 --> 00:14:11,552 그리고 다음 단계(state)에서는 h_t와 x_t+1가 입력이 됩니다. 138 00:14:11,552 --> 00:14:21,797 RNN에서 출력 값(y)을 가지려면 h_t 를 입력으로 하는 FC-Layer을 추가해야 합니다. 139 00:14:21,797 --> 00:14:27,327 FC-Layer는 매번 업데이트되는 Hidden state(h_t)를 기반으로 출력 값을 결정합니다. 140 00:14:27,327 --> 00:14:35,662 중요한 사실은 함수 f와 파라미터 W는 매 스텝 동일하다는 것입니다. 141 00:14:36,921 --> 00:14:43,434 자, RNN을 가장 간단하게 수식적으로 나타내려면 단순한(vanilla) RNN부터 시작하는게 좋겠군요 142 00:14:43,434 --> 00:14:46,866 지금 보이는 수식은 앞서 있던 수식과 동일합니다. 143 00:14:46,866 --> 00:14:52,483 "이전 hidden state"와 "현재 입력"을 받아서 "다음 hidden state"를 출력합니다. 144 00:14:52,483 --> 00:15:00,124 이를 수식적으로 가장 간단하게 표현해보면, 가중치 행렬 W_xh 와 입력 x_t의 곱으로 나타낼 수 있습니다. 145 00:15:00,124 --> 00:15:05,615 또한 가중치 행렬 W_hh도 있습니다. "이전 hidden state"와 곱해지는 값입니다. 146 00:15:05,615 --> 00:15:09,327 이렇게 두 입력(h,x) 에 대한 행렬 곱 연산이 있고 두 결과 값을 더해줍니다. 147 00:15:09,327 --> 00:15:13,514 그리고 System에 non-linearity를 구현하기 위해 tanh를 적용합니다. 148 00:15:13,514 --> 00:15:17,312 여러분 중에 왜 다른 non-linearity가 아닌 tanh를 쓰는지 궁금하신 분들도 계실 것입니다. 149 00:15:17,312 --> 00:15:20,594 지난 강의 동안에는 tanh가 안좋다고만 배웠는데 말이죠 150 00:15:20,594 --> 00:15:26,507 tanh와 관련된 문제는 lstm 배울 때 다시한번 다뤄드리도록 하겠습니다. 151 00:15:27,346 --> 00:15:33,394 자 이제 우리는 매 스텝마다 출력 y를 얻고 싶습니다. 152 00:15:33,394 --> 00:15:40,375 이를 위해서는 "hidden state"인 h_t 를 새로운 가중치 행렬 W_hy 와 곱해줍니다. 153 00:15:40,375 --> 00:15:44,826 가령 매 스텝에 출력 y는 class score가 될 수 있을 것입니다. 154 00:15:44,826 --> 00:15:51,487 Recurrent Neural Network는 크게 두 가지 방법으로 해석해 볼 수 있습니다. 155 00:15:51,487 --> 00:15:57,095 하나는 RNN이 hidden state를 가지며 이를 "재귀적으로" feed back 한다는 점입니다. 156 00:15:57,095 --> 00:16:05,914 RNN을 사실 이런 식으로 표현하면 많이 헷갈립니다. Multiple time steps을 unrolling 해서 보면 좋습니다. 157 00:16:05,914 --> 00:16:11,786 Unrolling을 하면 hidden states, 입/출력, 가중치 행렬들 간의 관계를 조금 더 명확히 이해할 수 있습니다. 158 00:16:11,786 --> 00:16:15,494 첫 step에서는 initial hidden state인 h_0 가 있습니다. 159 00:16:15,494 --> 00:16:22,415 대부분의 경우 h_0 는 0으로 초기화시킵니다. 그리고 입력 x_t가 있습니다. 160 00:16:22,415 --> 00:16:28,324 h_0와 x_1 이 함수 f_w의 입력으로 들어갑니다. 161 00:16:28,324 --> 00:16:36,154 f_w(h_0, x_1) 의 출력은 h_1 입니다. 이 과정이 반복됩니다. 이번에는 x_2 이 다음 입력으로 들어옵니다. 162 00:16:36,154 --> 00:16:42,847 f_w(h_1, x_2) 의 출력은 h_2가 됩니다. 163 00:16:42,847 --> 00:16:50,866 이 과정을 반복하면서 가변 입력 x_t 를 받습니다. 164 00:16:50,866 --> 00:16:58,036 이제는 조금 더 구체적인 이해를 위해서 행렬 W를 그려넣어 봅시다. 165 00:16:58,036 --> 00:17:03,415 여기에서 주목할 점은 "동일한 가중치 행렬 W"가 매번 사용된다는 점입니다. 166 00:17:03,415 --> 00:17:11,006 매번 h와 x는 달라지지만 W는 매번 동일합니다. 167 00:17:11,007 --> 00:17:20,786 앞서 Computational graph에서 동일한 node를 여러번 사용할 때 back prop gradient flow이 어떨지 배웠습니다. 168 00:17:20,786 --> 00:17:28,218 backward pass 시 dLoss/dW 를 계산하려면 행렬 W의 gradient를 전부 더해줬습니다. 169 00:17:28,218 --> 00:17:32,526 따라서 이 RNN 모델의 backprop을 위한 행렬 W의 그레디언트를 구하려면 170 00:17:32,526 --> 00:17:42,503 각 스텝에서의 W에 대한 그레디언트를 전부 계산한 뒤에 이 값들을 모두 더해주면 됩니다. 171 00:17:43,615 --> 00:17:47,727 Computational graph에 y_t도 넣어볼 수 있습니다. 172 00:17:47,727 --> 00:17:54,858 RNN의 출력 값 h_t가 또 다른 네트워크의 입력으로 들어가서 y_t를 만들어 냅니다. 173 00:17:54,858 --> 00:17:59,087 가량 y_t는 매 스텝의 class score가 될 수 있겠죠 174 00:17:59,087 --> 00:18:00,738 RNN의 Loss도 한번 살펴봅시다. 175 00:18:00,738 --> 00:18:14,068 각 시퀀스마다 Ground truth label이 있다고 해봅시다. 그러면 각 스텝마다 개별적으로 y_t에 대한 Loss를 계산할 수 있습니다. 176 00:18:14,068 --> 00:18:22,497 여기에서 Loss는 가령 softmax loss가 될 수 있겠죠 177 00:18:22,497 --> 00:18:27,887 RNN의 최종 Loss는 각 개별 loss들의 합입니다. 178 00:18:27,887 --> 00:18:34,196 각 단계에서 Loss가 발생하면 전부 더하여 최종 네트워크 Loss를 계산합니다. 179 00:18:34,196 --> 00:18:42,098 이 네트워크의 Backprop을 생각해보면 모델을 학습시키려면 dLoss/dW를 구해야 합니다. 180 00:18:42,098 --> 00:18:46,178 Loss flowing은 각 스텝에서 이루어집니다. 181 00:18:46,178 --> 00:18:49,840 이 경우에는 각 스텝마다 가중치 W에 대한 local gradient를 계산할 수 있습니다. 182 00:18:49,840 --> 00:18:54,343 이렇게 개별로 계산된 local gradient를 최종 gradient에 더합니다. 183 00:18:55,597 --> 00:19:01,188 그렇다면 "many to one" 이라면 어떨까요? 가령 감정분석(sentiment analysis) 처럼 말입니다. 184 00:19:01,188 --> 00:19:05,799 이 경우에는 네트워크의 최종 hidden state에서만 결과 값이 나올 것입니다. 185 00:19:05,799 --> 00:19:11,868 최종 hidden state가 전체 시퀀스의 내용에 대한 일종의 요약으로 볼 수 있기 떄문입니다. 186 00:19:11,868 --> 00:19:14,788 그렇다면 "one to many" 의 경우에는 어떨까요? 187 00:19:14,788 --> 00:19:19,319 "고정 입력" 을 받지만 "가변 출력"인 네트워크입니다. 188 00:19:19,319 --> 00:19:26,050 이 경우에는 대게 고정 입력은 모델의 initial hidden state를 초기화시키는 용도로 사용합니다. 189 00:19:26,050 --> 00:19:30,079 그리고 RNN은 모든 스텝에서 출력 값을 가집니다. 190 00:19:30,079 --> 00:19:36,915 이렇게 가변 출력을 가지는 경우에도 이렇게 그래프를 Unroll 해 볼 수 있습니다. 191 00:19:38,490 --> 00:19:44,308 "sequence to sequent" 모델에 대해서 알아보겠습니다. 가령 machine tranlation 에 사용할 수 있는 모델입니다. 192 00:19:44,308 --> 00:19:47,648 "가변 입력" 과 "가변 출력" 을 가지는 모델입니다. 193 00:19:47,648 --> 00:19:52,398 우리는 이 모델을 "many to one" 모델과 "one to many" 모델의 결합으로 볼 수 있습니다. 194 00:19:52,398 --> 00:19:56,900 두 개의 스테이지로 구성되는 것이죠. encoder와 decoder 구조입니다. 195 00:19:56,900 --> 00:20:02,159 encoder는 가변 입력을 받습니다. 가령 English sentence가 될 수 있겠죠 196 00:20:02,159 --> 00:20:08,110 그리고 encoder의 final hidden state 를 통해 전체 sentence를 요약합니다. 197 00:20:08,110 --> 00:20:15,769 Encoder 에서는 "many to one" 을 수행합니다. "가변 입력"을 하나의 벡터로 요약합니다. 198 00:20:15,769 --> 00:20:23,111 반면 Decoder는 "one to many"를 수행합니다. 입력은 앞서 요약한 "하나의 벡터" 입니다. 199 00:20:23,111 --> 00:20:28,969 그리고 decoder는 "가변 출력"을 내뱉습니다. 가령 다른 언어로 변역된 문장이 될 수 있겠죠 200 00:20:28,969 --> 00:20:34,609 "가변 출력" 은 매 스텝 적절한 단어를 내뱉습니다. 201 00:20:34,609 --> 00:20:38,199 그림처럼 전체 Computational graph를 풀어서 전체 학습과정을 해석해보면 202 00:20:38,199 --> 00:20:44,692 Output sentence의 각 losses를 합해서 Backprob 을 진행합니다. 203 00:20:44,692 --> 00:20:50,940 조금 더 구체적인 예를 살펴보겠습니다. 대게는 RNN 은 Language modeling에서 자주 사용합니다. 204 00:20:50,940 --> 00:21:00,908 Language modeling 문제에서 하고싶은 것은 바로 "어떻게 자연어(natural lang)을 만들어낼지 입니다. 205 00:21:00,908 --> 00:21:06,601 가령 문자(characters) 를 내뱉는 모델이라면 매 스텝 어떻게 문자를 생성해 낼지를 풀어야 합니다. 206 00:21:06,601 --> 00:21:10,769 단어(word) 를 내뱉는 모델이라면 매 스텝 어떻게 단어를 생성해 낼 지를 풀어야겠죠 207 00:21:10,769 --> 00:21:14,740 우선은 간단한 예제를 위해서 character level language model 을 살펴보겠습니다. 208 00:21:14,740 --> 00:21:22,780 네트워크는 문자열 시퀀스를 읽어드리고, 현재 문맥에서 다음 문자를 예측해야 합니다. 209 00:21:22,780 --> 00:21:33,884 이번 예제에서는 간단하게 단어가 [h,e,l,o] 만 있습니다. 그리고 학습시킬 문장은 "h, e, l, l, o" 입니다. 210 00:21:33,884 --> 00:21:49,689 Train time에서는 training sequence("hello") 의 각 단어들을 입력으로 넣어줘야 합니다. 211 00:21:49,689 --> 00:21:53,980 "hello" 가 RNN의 x_t입니다. 212 00:21:53,980 --> 00:22:01,039 우선 입력은 한 글자(letter)씩 입니다. 네트워크도 적절한 글자들을 출력해야 합니다. 213 00:22:01,039 --> 00:22:07,460 일반적으로 입력을 넣어주는 방법이 있습니다. 우선 vocabulary는 총 네 가지입니다.[h, e, l, o] 214 00:22:07,460 --> 00:22:12,589 각 글자는 하나의 벡터로 표현할 수 있습니다. 이 벡터는 1이 하나 있고 나머지는 0인 벡터입니다. 215 00:22:12,589 --> 00:22:16,628 벡터에서 해당 글자 위치만 1로 표시합니다. 216 00:22:16,628 --> 00:22:22,324 이 단순한 예제에서는 글자가 h, e, l, o 뿐입니다. 따라서 4-d 벡터로 표현할 수 있습니다. 217 00:22:22,324 --> 00:22:28,684 가령 h를 벡터로 표현하는 경우([1,0,0,0]) h에 해당하는 자리만 1이고 나머지는 0입니다. 218 00:22:28,684 --> 00:22:33,139 이런 식으로 다은 문자들도 벡터로 표현할 수 있습니다. 219 00:22:34,914 --> 00:22:41,874 Forward pass에서 네트워크가 어떻게 동작하는지 살펴봅시다. 우선 첫 스텝에서는, 입력 문자 'h' 가 들어옵니다. 220 00:22:41,874 --> 00:22:48,594 첫 번째 RNN cell로는 'h' 가 들어갑니다. 그러면 네트워크는 y_t를 출력합니다. 221 00:22:48,594 --> 00:22:56,024 y_t는 어떤 문자가 'h' 다음에 나올 것 같은지를 예측한 값입니다. 222 00:22:56,024 --> 00:23:01,405 이 예제에서는 'h' 다음에는 'e' 를 예측해야 정답입니다. 223 00:23:01,405 --> 00:23:06,861 하지만 현재 이 모델은 다음에 나올 글자가 'o' 라고 예측하고 있습니다. 224 00:23:07,850 --> 00:23:13,889 잘못 예측한 경우입니다. softmax loss가 이 예측이 얼마나 형편없는지 알려줄 것입니다. 225 00:23:13,889 --> 00:23:19,741 다음 스텝에서는 두 번째 단어 'e' 가 입력으로 들어갑니다. 이런 과정이 반복됩니다. 226 00:23:19,741 --> 00:23:27,271 우선 'e' 벡터입니다. 그리고 "이전 hidden state"와 함께 "새로운 hidden state" 를 만들어내죠 227 00:23:27,271 --> 00:23:31,912 이제는 두번째 hidden state를 이용해서 적절한 값을 예측해야 합니다. 228 00:23:31,912 --> 00:23:36,810 'hello' 를 예측해야 하므로 'e' 가 입력이라면 'l' 을 예측해야합니다. 229 00:23:36,810 --> 00:23:41,954 이 경우 'l' 의 예측 치가 상당히 낮기 때문에 Loss가 높습니다. 230 00:23:44,244 --> 00:23:50,343 이 과정을 반복합니다. 모델을 다양한 문장으로 학습시킨다면 231 00:23:50,343 --> 00:23:58,596 결국 모델은 이전 문장의 문맥을 참고해서 다음 문자가 무엇일지를 학습해야 할 것입니다. 232 00:23:59,893 --> 00:24:01,655 그렇다면 이 모델의 Test time은 어떨까요? 233 00:24:01,655 --> 00:24:07,594 이렇게 학습시킨 모델을 활용할 수 있는 방법들 중 하나는 Model로부터 Sampling 하는 것입니다. 234 00:24:07,594 --> 00:24:15,103 다시말해, Train time에 모델이 봤을 법한 문장을 모델 스스로 생성해 내는 것입니다. 235 00:24:15,103 --> 00:24:22,716 우선 모델에게 문장의 첫 글자만 줍니다. 이 경우에는 'h' 가 되겠군요 236 00:24:22,716 --> 00:24:27,295 RNN 의 첫 스텝의 입력은 'h'가 될 것입니다. 237 00:24:27,295 --> 00:24:32,916 'h'가 주어지면 모든 문자(h,e,l,o) 에 대한 스코어를 얻을 수 있습니다(output layer) 238 00:24:32,916 --> 00:24:37,501 Test time에서는 이 스코어를 "sampling"(다음 글자 선택)에 이용 합니다. 239 00:24:37,501 --> 00:24:41,421 스코어를 확률분포로 표현하기 위해서 sofrmax 함수를 사용할 수 있습니다. 240 00:24:41,421 --> 00:24:47,362 문장의 두 번째 글자를 선택하기 위해서 이 확률분포를 이용합니다. 241 00:24:47,362 --> 00:24:54,771 이 경우에 'e'가 뽑힐 확률(13%)이 엄청 낮았음에도 아주 운좋게 'e'가 샘플링되었습니다. 242 00:24:54,771 --> 00:25:02,492 이제는 확률 분포에서 운좋게 뽑힌 'e' 를 다음 스텝의 네트워크 입력으로 넣어 줄 것입니다. 243 00:25:02,492 --> 00:25:15,008 'e' 를 다시 벡터[0,1,0,0]로 만들어주고 다음 입력으로 넣어주면 네트워크는 두번째 출력을 만들어 냅니다. 244 00:25:15,008 --> 00:25:20,722 이 학습된 모델만 가지고 새로운 문장을 만들어내기 위해 이 과정을 반복합니다. 245 00:25:20,722 --> 00:25:27,712 전체 문장을 만들어내기 위해 타임 스텝마다 확률 분포에서 문자를 하나씩 뽑아냅니다. 246 00:25:27,712 --> 00:25:28,545 질문 있나요? 247 00:25:34,792 --> 00:25:41,315 질문은 "가장 높은 스코어를 선택하면 그만인데 왜 굳이 확률분포에서 샘플링하는지" 입니다. 248 00:25:41,315 --> 00:25:46,555 이 예제의 경우에는 가장 스코어가 높은 값만 사용하면 올바른 결과를 낼 수 없었습니다. (e 스코어가 낮았음) 249 00:25:47,451 --> 00:25:51,512 따라서 확률분포에서 샘플링을 했기 때문에 hello를 잘 만들 수 있었습니다. 250 00:25:51,512 --> 00:25:54,384 실제로는 두 경우 모두 사용할 수 있습니다. (확률 분포에서 샘플링 or 그냥 가장 높은 값) 251 00:25:54,384 --> 00:25:59,482 어떤 경우에는 argmax probability만 사용할 수 있습니다. (가장 높은 값을 취함) 더 안정적인 방법일 수 있습니다. 252 00:25:59,482 --> 00:26:04,264 하지만 확률 분포에서 샘플링하는 방법을 사용하면 일반적으로는 모델에서의 다양성을 얻을 수 있습니다. 253 00:26:04,264 --> 00:26:11,421 만약 항상 같은 접두사(예제에서 h)라던지, 이미지라면 같은 사진이라던지를 모델 입력으로 주면 254 00:26:11,421 --> 00:26:20,032 argmax을 하지 않고 샘플링을 하게되면 그럴듯한 다양한 문장을 출력할 수 있게 됩니다. 255 00:26:20,032 --> 00:26:23,824 첫 스텝에서 어떤 값이 샘플링되는지에 따라서 출력이 다양해 질 수 있는 것입니다. 256 00:26:23,824 --> 00:26:29,213 샘플링 하는 방법은 다양한 출력을 얻을 수 있다는 관점에서 좋은 방법이 될 수 있습니다. 257 00:26:29,213 --> 00:26:30,630 다른 질문 있나요? 258 00:26:35,143 --> 00:26:40,435 [학생이 질문] 259 00:26:46,162 --> 00:26:51,373 질문은 "Test time에 sofrmax vector를 one hot vector 대신에 넣어줄 수 있는지" 입니다. 260 00:26:51,373 --> 00:26:56,782 두 가지 문제가 발생할 수 있습니다. 첫 째는 그렇게 되면 입력이 Train time에서 본 입력과 달라집니다. 261 00:26:56,782 --> 00:27:05,413 모델에게 Train time에서 보지 못한 입력값을 주게되면 대게는 모델이 아무것도 하지 못합니다. 262 00:27:05,413 --> 00:27:09,112 두 번째 문제는 실제로는 vocabularies가 아주 크다는 것입니다. 263 00:27:09,112 --> 00:27:13,202 예제에서는 voca가 4개 뿐이 없어서 크게 문제될 것이 없겠지만 264 00:27:13,202 --> 00:27:18,773 한 스텝마다 단어(word)를 생성하는 모델이라고 보면 voca 안에는 이세상의 모든 영어단어가 들어가야합니다. 265 00:27:18,773 --> 00:27:21,162 voca는 수만개 이상의 요소를 가지게 되겠죠 266 00:27:21,162 --> 00:27:30,533 실제론 one hot vector를 sparse vector operation 으로 처리합니다. (dense vector가 아닌) 267 00:27:30,533 --> 00:27:36,827 10,000dim softmax vector를 연산해야 한다면 연산량이 어마어마 할 것입니다. 268 00:27:36,827 --> 00:27:40,302 Test time에서도 one hot을 사용하는 이유입니다. 269 00:27:42,121 --> 00:27:47,104 이런 모델의 경우 시퀀스 스텝마다 출력값이 존재합니다. 270 00:27:47,104 --> 00:27:51,543 이 출력값들의 Loss를 계산해 final loss를 얻는데 이를 "backpropagation through time" 라고 합니다. 271 00:27:51,543 --> 00:27:57,053 이 경우, forward pass의 경우에는 전체 시퀀스가 끝날 때 까지 출력값이 생성됩니다. 272 00:27:57,053 --> 00:28:00,762 반대로 backward pass에서도 전체 시퀀스를 가지고 Loss를 계산해야 합니다. 273 00:28:00,762 --> 00:28:06,162 하지만 이 경우 시퀀스가 아주 긴 경우에는 문제가 될 소지가 있습니다. 274 00:28:06,162 --> 00:28:15,453 가령 Wikipedia 전체 문서로 모델을 학습시킨다고 해봅시다. 275 00:28:15,453 --> 00:28:23,328 이 경우 학습이 정말 느릴 것입니다. gradient를 계산하려면 Wikipedia 전체 문서를 다 거쳐야 할 것입니다. 276 00:28:23,328 --> 00:28:27,813 Wikipedia 문서 전체에 대한 gradient를 계산하고 나면 gradient update가 1회 수행됩니다. 277 00:28:27,813 --> 00:28:34,172 이 과정은 아주 느릴 것입니다. 모델이 수렴될리 없겠죠. 메모리 사용량도 어마어마할 것입니다. 278 00:28:34,172 --> 00:28:39,933 실제로는 "truncated backpropagation" 를 통해서 backprob 을 근사시키는 기법을 사용합니다. 279 00:28:39,933 --> 00:28:45,562 이 방법의 아이디어는 비록 입력 스퀀스가 엄청나게 길어서 무한대라고 할지라도 280 00:28:45,562 --> 00:28:56,232 Train time에 한 스텝을 일정 단위로 자릅니다. 대략 100 정도로 말이죠 281 00:28:56,232 --> 00:29:06,261 100 스텝만 forward pass를 하고 이 서브스퀀스의 Loss를 계산합니다. 그리고 gradient step을 진행하는 것이죠. 282 00:29:06,261 --> 00:29:12,064 이 과정을 반복합니다. 다만 이전 batch에서 계산한 hidden states는 계속 유지합니다. 283 00:29:12,064 --> 00:29:20,631 다음 Batch의 forward pass를 계산할 때는 이전 hidden state를 이용합니다. 284 00:29:20,631 --> 00:29:28,124 그리고 gradient step은 현재 Batch에서만 진행합니다. 285 00:29:28,124 --> 00:29:32,760 이 방법을 "truncated backpropagation through time" 이라고 합니다. 286 00:29:32,760 --> 00:29:38,250 이 과정을 반복합니다. 이전 batch에서 hidden states를 가져와서 foward pass를 수행하고 287 00:29:38,250 --> 00:29:43,840 backprob은 현재 배치만큼만 진행합니다. 288 00:29:43,840 --> 00:29:49,872 이 방법은 Stocastic gradient descent의 시퀀스 데이터 버전이라고 볼 수 있습니다. 289 00:29:49,872 --> 00:29:53,690 지난 시간이 Data Sets이 엄청 큰 경우 어떻게 학습시켜야 하는지 배웠습니다. 290 00:29:53,690 --> 00:29:58,720 Large datasets에서는 전체 데이터로 gradients를 계산하기에는 계산량이 너무 컸습니다. 291 00:29:58,720 --> 00:30:02,520 그래서 대신에 mini batch를 사용해서 small samples만 가지고 계산했습니다. 292 00:30:02,520 --> 00:30:08,053 그리고 mini batch만을 이용해서 gradient를 계산했습니다. 가령 Image classification에서 그랬었죠 293 00:30:08,053 --> 00:30:08,886 질문있나요? 294 00:30:12,441 --> 00:30:15,989 질문은 "RNN이 Markov Assumption 을 따르는지" 입니다. 295 00:30:15,989 --> 00:30:20,581 그렇지 않습니다. 왜냐하면 RNN은 이전 hidden state를 계속해서 앞으로 가져가기 때문입니다.(영원히) 296 00:30:21,442 --> 00:30:25,792 마르코 비아 가정을하고있다. 숨겨진 상태를 조건으로, 297 00:30:25,792 --> 00:30:31,101 그러나 숨겨진 상태가 우리가 필요로하는 모든 것입니다. 미래를 예언하기 시퀀스의 298 00:30:31,101 --> 00:30:35,941 하지만 그 가정은 일종의 건축입니다. 재발 성 신경 네트워크 공식 출발점에서. 299 00:30:35,941 --> 00:30:39,032 그리고 그것은 정말로 특별하지 않습니다. 시간을 통한 전파를 역전 시키십시오. 300 00:30:39,032 --> 00:30:51,239 Truncated backprop은 very large sequence data의 gradient를 근사시키는 방법입니다. 301 00:30:52,677 --> 00:30:59,649 RNN을 구현하려면 코드도 엄청 복잡하고 어려울 것 같아 보이지만 사실은 그렇지 않습니다. 엄청 간결합니다. 302 00:30:59,649 --> 00:31:07,474 Andrej가 min-char-rnn 이라는 코드를 만들어놨습니다. 112 줄의 코드로 RNN 전체 과정을 구현하였습니다. 303 00:31:07,474 --> 00:31:11,725 vocabulary를 만들고, truncated back propagation 을 수행하는 모델을 구현한 코드입니다. 304 00:31:11,725 --> 00:31:16,584 그리고 실제 Model을 학습시키고 샘플링도 할 수 있습니다. 305 00:31:16,584 --> 00:31:20,862 RNN을 구성하는 것이 엄청나게 어려워 보일 수 있지만 사실은 그렇지 않습니다. 306 00:31:20,862 --> 00:31:27,954 슬라이드만 보면 잘 모르실 수 있습니다. 여러분이 직접 파일을 열어서 코드를 한줄 씩 살펴보시기 바랍니다. 307 00:31:27,954 --> 00:31:34,473 Numpy로만 작성된 dependencies가 없는 코드입니다. 코드를 읽기에도 비교적 쉽습니다. 308 00:31:35,584 --> 00:31:41,593 RNN Language model 로 아주 재미있는 것들을 학습시킬 수 있습니다. 309 00:31:41,593 --> 00:31:52,304 RNN으로 어떤 문장이건 학습시킬 수 있습니다. 인터넷에서 아무 문장이나 긁어와서 학습시킬 수 있습니다. 310 00:31:52,304 --> 00:32:02,634 가령 셰익스피어의 작품들을 RNN으로 학습시켜 볼 수 있습니다. 311 00:32:02,634 --> 00:32:11,584 학습 초기에는 모델이 의미없는 문장들만 뱉어냅니다. 하지만 학습을 시키면 시킬수록 의미있는 문장을 만들어냅니다. 312 00:32:11,584 --> 00:32:18,224 학습이 잘 끝나면 상당히 셰익스피어 풍의 문장들을 만들어냅니다. 313 00:32:18,224 --> 00:32:24,754 "Why do what that day... replied" 어쩄든 상당히 셰익스피어의 문장 처럼 보입니다. 314 00:32:24,754 --> 00:32:31,264 더 학습을 많이 시키면 훨씬 더 긴 문장들도 만들어낼 수 있습니다. 315 00:32:31,264 --> 00:32:35,864 RNN을 이용하면 이런 셰익스피어 풍의 문장과 같은 여러가지 신기한 것들을 학습시킬 수 있습니다. 316 00:32:35,864 --> 00:32:40,016 모델이 HEAD에 발화자를 넣어야한다는 것을 압니다. (예 : "VIOLA:") 317 00:32:40,016 --> 00:32:45,565 그리고 바로 밑에 셰익스피어풍의 문장들을 만들어냅니다. 318 00:32:45,565 --> 00:32:47,744 다른 문장을 시작할 때 한 줄을 비워야 하는 것도 압니다. 319 00:32:47,744 --> 00:32:52,958 이건 엄청난 것입니다. 문장의 구조를 아주 완벽하게 학습했습니다. 320 00:32:52,958 --> 00:33:02,725 훨씬 더 엄청난 것도 있습니다. 인터넷에서 찾았는데요, 혹시 여기 수학 전공자가 있나요? 321 00:33:02,725 --> 00:33:07,325 "algebraic topology" 수업을 들어본 분이 계신가요? 몇 분정도 계시는군요 322 00:33:07,325 --> 00:33:15,114 여러분이 저보다 "algebraic topology"를 더 잘 하시겠네요. 제가 얼마전에 온라인"algebraic topology" 교과서를 찾았습니다. 323 00:33:15,114 --> 00:33:19,554 이 교과서 파일은 수학적인 내용으로 가득 차 있습니다. 324 00:33:19,554 --> 00:33:26,325 그리고 수식이 LaTex 문법으로 작성되어 있습니다. LaTex을 쓰면 수식을 코드로 작성할 수 있습니다. 325 00:33:26,325 --> 00:33:33,146 그러면 algebraic topology 교과서의 LaTex 코드를 우리가 만든 RNN Language Model로 학습시킬 수 있습니다. 326 00:33:33,146 --> 00:33:41,446 자 이걸 학습시키게 되면 (웃음) 이런 식으로 algebraic topology스러운 문장들을 만들어낼 수 있습니다. 327 00:33:41,446 --> 00:33:46,679 모델이 수식도 만들어 냅니다. 328 00:33:46,679 --> 00:33:52,773 "To prrov study that F_sub U is a covering of x prime.. blah blah" (왼쪽 4번째 문단) 329 00:33:52,773 --> 00:33:56,576 unions도 만들어내고, proofs의 끝에 사각형도 만들어냅니다. 330 00:33:56,576 --> 00:34:00,026 lemmas도 만들어내고 이전 lemmas를 참조하기도 합니다. 331 00:34:00,026 --> 00:34:08,417 bi-lemma question 라던지 R 같은 기하학적인 내용도 모두 만들어냅니다. 엄청 대단하죠 332 00:34:09,496 --> 00:34:12,913 diagrams을 만들어내려고도 합니다. 333 00:34:14,239 --> 00:34:19,313 commutative diagram은 algebraic topology에서 아주 많이 사용됩니다. 334 00:34:19,313 --> 00:34:26,379 모델이 이 다이어그램을 열심히 만들어 내려 했지만 물론 이 다이어그램은 아무 의미가 없습니다. 335 00:34:26,380 --> 00:34:32,728 그리고 또 재미있는 점 중 하나는 모델이 "증명 생략" 도 학습합니다. 336 00:34:32,728 --> 00:34:39,694 가끔 이런 경우가 있죠. "theorem : blah blah blah, proof : 생략" 337 00:34:39,695 --> 00:34:45,392 교과서에서 증명이 생각되는 부분도 모델이 정확하게 학습한 것입니다. 338 00:34:47,831 --> 00:34:53,497 또 다른 재미있는 것들도 할 수 있습니다. 이번에는 Linux Kernel의 전체 소스코드를 학습시켰습니다. 339 00:34:53,498 --> 00:34:56,801 코드를 character level로 학습시켰습니다. 340 00:34:56,801 --> 00:35:01,483 학습된 모델에서 샘플링을 해보면 C 소스코드 스러운 것들이 나옵니다. 341 00:35:01,483 --> 00:35:06,192 모델이 if 문 작성법을 알고 있습니다. 코드 짜는 스킬이 어마어마 합니다. 342 00:35:06,192 --> 00:35:09,552 들여쓰기와 중괄호를 쓰는법도 잘 알고있습니다. 343 00:35:09,552 --> 00:35:15,052 주석다는 법도 알고있습니다. 물론 뜻은 아무 의미도 없습니다. 344 00:35:15,052 --> 00:35:23,355 이 모델의 문제점 중 하나는. 변수를 선언해 놓고 쓰지를 않다는 것입니다. 345 00:35:23,355 --> 00:35:27,554 반대로 선언하지도 않은 변수를 쓰기도 합니다. 이 코드는 컴파일되지 않습니다. 346 00:35:27,554 --> 00:35:30,555 이 코드를 Linux에 pull request 하고싶진 않네요 347 00:35:30,555 --> 00:35:37,867 이 모델은 GNU license를 추가하는 법도 압니다. 348 00:35:37,867 --> 00:35:44,962 GNU license 다음에 include 가 나오고 include 가 몇 번 나오고 소스코드가 나옵니다. 349 00:35:44,962 --> 00:35:48,836 이 모델은 데이터의 일반적인 구조를 아주 잘 학습했습니다. 350 00:35:48,836 --> 00:35:53,398 다시 한번 말씀드립니다만, 우리가 모델에게 요청한 것은 그저 시퀀스의 다음 문자를 예측하라는 것이였습니다. 351 00:35:53,398 --> 00:35:55,406 구조에 대해서는 전혀 말해주지 않았죠 352 00:35:55,406 --> 00:36:03,355 하지만 모델은 학습과정 동안에 시퀀스 데이터의 숨겨진 구조(latent structure)를 알아서 학습합니다. 353 00:36:05,808 --> 00:36:10,246 결국 알아서 코드를 작성하게 된 것입니다. 아주 대단합니다. 354 00:36:10,246 --> 00:36:20,856 저와 Andrej가 몇 년전에 낸 논문이 있습니다. 학습한 모델이 도대체 어떤 방식으로 동작하는지 알아내고 싶었습니다. 355 00:36:20,856 --> 00:36:28,165 RNN에는 hidden vector가 있고 이 vector가 계속 업데이트됩니다. 356 00:36:28,165 --> 00:36:34,176 우리는 그 Vector를 추출해보면 해석 가능한 의미있는 것들이 나올수도 있지 않을까 추측해 보았습니다. 357 00:36:34,176 --> 00:36:39,917 그래서 우리는 RNN language model을 특정 dataset으로 학습시키고, 358 00:36:39,917 --> 00:36:47,923 그리고 hidden vector를 하나 뽑아서 어떤 값들이 들어있는지 살펴보기로 했습니다. 359 00:36:47,923 --> 00:36:52,206 이 서로 다른 hidden states가 도대체 어떤 것들을 예의주시하는지 알아보기 위해서였죠 360 00:36:52,206 --> 00:36:56,406 이 실험을 해보면, 대부분의 hidden state는 아무 의미 없는 패턴으로 예의 주시하고 있습니다. 361 00:36:56,406 --> 00:37:02,686 여기서 우리가 한 일은 vector 하나를 뽑은 다음에 이 시퀀스를 다시 한번 forward 시켜 보는 것입니다. 362 00:37:02,686 --> 00:37:10,876 여기에서 각 색깔은, 시퀀스를 읽는 동안에 앞서 뽑은 hidden vector의 값을 의미합니다. 363 00:37:10,876 --> 00:37:15,883 RNN의 대부분의 Cell은 해석하기 어렵습니다. 364 00:37:15,883 --> 00:37:21,396 대부분은 다음에 어떤 문자가 와야할 지 알아내기 위한 low level language modeling 정도로밖에 보이지 않습니다. 365 00:37:21,396 --> 00:37:23,438 하지만 일부는 해석해볼만 합니다. 366 00:37:23,438 --> 00:37:26,375 그러다가 따옴표(quotes)를 찾는 벡터를 알아냈습니다. 367 00:37:26,375 --> 00:37:32,486 이 vector가 하는 일을 살펴보면 처음에는 계속 off off off off ... 입니다. 파란색이죠. (파란색이 off) 368 00:37:32,486 --> 00:37:38,303 그러다가 따옴표를 만나면 값이 켜집니다(빨간색) 그리고 따옴표가 닫히기 전까지 유지됩니다. 369 00:37:39,187 --> 00:37:42,598 그러다가 두 번째 따옴표를 만나면 다시 값이 꺼집니다. 370 00:37:42,598 --> 00:37:48,856 이런 식으로, 그저 우리는 모델이 다음 문자를 예측하도록 학습시켰을 뿐이지만 모델은 더 유용한 것들을 학습하는 것입니다. 371 00:37:48,856 --> 00:37:54,222 그런 유용한 것들을 학습하기 위해서 그 Cell이 따옴표를 감지할 수 있게 된 것입니다. 372 00:37:54,222 --> 00:38:00,104 우리는 또, 줄 바꿈을 위해서 현재 줄의 단어 갯수를 세는 듯해 보이는 Cell도 발견했습니다. 373 00:38:00,104 --> 00:38:07,055 처음에는 0으로 시작했다가. 줄이 점점 길어지면 점점 빨간색으로 변합니다. 374 00:38:07,055 --> 00:38:11,976 점점 증가하다가 줄바꿈이 이루어지면 다시 0으로 리셋됩니다. 375 00:38:11,976 --> 00:38:19,545 이 Cell은 언제 모델이 new line characters을 필요로 할 지 지속적으로 추적하는 역할을 한다고 볼 수 있습니다. 376 00:38:19,545 --> 00:38:22,987 그리고 우리는 linux 코드를 학습시킬 때 발견한 것도 있습니다. 377 00:38:22,987 --> 00:38:33,838 우리는 if 문의 조건부에서 값이 켜지는 Cell을 발견했습니다. 이 Cell은 조건부의 내부와 외부를 구별할 수 있습니다. 378 00:38:33,838 --> 00:38:35,806 이를 통해 모델이 시퀀스를 더 잘 학습할 수 있도록 도와줍니다. 379 00:38:35,806 --> 00:38:44,765 그 밖에도 Comments를 찾아내거나 혹은 들여쓰기 레벨을 세는 듯한 Cell도 발견 했습니다. 380 00:38:44,765 --> 00:38:50,758 정말 놀라운 일입니다. 우리는 그저 다음 문자를 예측하는 모델을 학습시켰을 뿐인데 381 00:38:50,758 --> 00:38:55,646 결국 모델은 입력 데이터의 구조를 학습하게 되었기 때문입니다. 382 00:38:57,161 --> 00:39:05,528 우리는 Computer Vision 수업이니 다시 Computer Vision 에 관련된 예시로 돌아가 보겠습니다. 383 00:39:05,528 --> 00:39:08,747 앞서 Image Captioning Model에 대해서 몇 번 언급했었습니다. 384 00:39:08,747 --> 00:39:14,376 이 모델은 입력은 이미지이고 출력은 자연어로 된 Caption 입니다. 385 00:39:14,376 --> 00:39:19,787 이 문제를 다루는 몇몇 논문들이 있습니다. 다들 접근 방법은 비슷합니다. 386 00:39:19,787 --> 00:39:25,026 이 그림은 그 논문들 중 저희 연구실에서 나온 논문입니다. 아주 "공정한 기준으로?" 예시를 이 논문으로 선택헀습니다. 387 00:39:26,876 --> 00:39:35,608 우선 Caption은 가변길이 입니다. Caption 마다 다양한 시퀀스 길이를 가지고 있습니다. 388 00:39:35,608 --> 00:39:39,947 여기에 RNN Language Model가 아주 잘 어울립니다. 389 00:39:39,947 --> 00:39:50,379 모델에는 입력 이미지를 받기 위핸 CNN이 있습니다. CNN은 지금까지 아주 많이 살펴봤었죠 390 00:39:50,379 --> 00:39:58,928 CNN은 요약된 이미지정보가 들어있는 Vector를 출력합니다. 이 Vector는 RNN의 초기 Step의 입력으로 들어갑니다. 391 00:39:58,928 --> 00:40:02,888 그러면 RNN은 Caption에 사용할 문자들을 하나씩 만들어냅니다. 392 00:40:02,888 --> 00:40:06,425 그렇다면 이 모델을 학습시킨 후에 Test time에 어떻게 동작하는지 알아봅시다. 393 00:40:06,425 --> 00:40:11,178 지금까지 살펴봤던 character level languate model과 아주 유사합니다. 394 00:40:11,178 --> 00:40:18,638 우선 입력 이미지를 받아서 CNN의 입력으로 넣습니다. 다만 softmax scores를 사용하지 않고 395 00:40:18,638 --> 00:40:24,915 직전의 4,096-dim vector를 출력으로 합니다. 396 00:40:24,915 --> 00:40:31,377 이 vector를 이용해서 전체 이미지 정보를 요약하는데 사용할 것입니다. 397 00:40:31,377 --> 00:40:39,528 앞서 RNN language models에서 배웠듯이 모델이 문장을 생성해 내기에 앞서 초기 값을 넣어줘야 합니다. 398 00:40:39,528 --> 00:40:49,006 이 경우에는 입력이 특별합니다. 모델에게 "여기 이미지 정보가 있으니 이 조건에 맞는 문장을 만들어줘!" 라고 시작해야합니다. 399 00:40:49,006 --> 00:40:57,107 이전 까지의 모델에서는 RNN 모델이 두 개의 가중치 행렬을 입력으로 받았습니다. 하나는 현재 스텝의 입력이고 400 00:40:57,107 --> 00:41:01,240 다른 하나는 이전 스텝의 Hidden state 이었죠. 그리고 이 둘을 조합해서 다음 hidden state를 얻었습니다. 401 00:41:01,240 --> 00:41:04,678 하지만 이제는 이미지 정보도 더해줘야 합니다. 402 00:41:04,678 --> 00:41:13,105 사람마다 모델에 이미지정보를 추가하는 방법이 다르겠지만 가장 쉬운 방법은 세 번째 가중치 행렬을 추가하는 것입니다. 403 00:41:14,561 --> 00:41:18,598 다음 hidden state를 계산할 때마다 모든 스텝에 이 이미지 정보를 추가합니다. 404 00:41:18,598 --> 00:41:23,635 자 이제는 vocabulary의 모든 스코어들에 대한 분포를 계산할 차례입니다. 405 00:41:23,635 --> 00:41:27,307 이 문제에서 vocabulary는 "모든 영어 단어들" 과 같이 엄청나게 큽니다. 406 00:41:27,307 --> 00:41:32,099 그 분포에서 샘플링을 하고 그 단어를 다음 스텝의 입력으로 다시 넣어줄 것입니다. 407 00:41:32,099 --> 00:41:39,546 샘플링된 단어(y0)가 들어가면 다시 vacab에 대한 분포를 추정하고 다음 단어를 만들어냅니다. 408 00:41:39,546 --> 00:41:47,538 모든 스텝이 종료되면 결국 한 문장이 만들어집니다. 409 00:41:47,538 --> 00:41:54,347 이 때, 라는 특별한 토큰이 있는데 이는 문장의 끝을 알려줍니다. 410 00:41:54,347 --> 00:42:00,328 가 샘플링되면 모델은 더이상 단어를 생성하지 않으며 이미지에 대한 caption이 완성됩니다. 411 00:42:00,328 --> 00:42:06,739 Train time에는 모든 caption의 종료지점에 토큰을 삽입합니다. 412 00:42:06,739 --> 00:42:10,907 네트워크가 학습하는 동안에 시퀀스의 끝에 토큰을 넣어야 한다는 것을 알려줘야 하기 때문입니다. 413 00:42:10,907 --> 00:42:16,848 학습이 끝나고 Test time에는 모델이 문장 생성을 끝마치면 토큰을 샘플링합니다. 414 00:42:16,848 --> 00:42:20,139 이 모델은 완전히 supervised learning으로 학습시킵니다. 415 00:42:20,139 --> 00:42:24,763 따라서 이 모델을 학습시키기 위해서는 natural language caption이 있는 이미지를 가지고 있어야 합니다. 416 00:42:24,763 --> 00:42:28,666 이 Task를 위한 가장 큰 데이터셋은 아마 Microsoft COCO 데이터셋이 아닐까 싶습니다. 417 00:42:28,666 --> 00:42:47,837 이 모델을 학습시키기 위해서는 natural language model과 CNN을 동시에 backp 시킬 수 있습니다. 418 00:42:47,837 --> 00:42:52,438 이 모델을 학습시키고 나면 상당히 그럴듯한 결과를 보입니다. 419 00:42:52,438 --> 00:42:56,689 지금 보이는 것들이 실제 모델의 결과입니다. 420 00:42:56,689 --> 00:43:00,995 고양이가 여행용 가방에 앉아있습니다. "A cat sitting on a suitcase on the floor" 421 00:43:00,995 --> 00:43:02,583 상당히 인상적인 결과입니다. 422 00:43:02,583 --> 00:43:04,975 고양이가 나뭇가지에 앉아있습니다. "A cat is sitting on a tree branch" 423 00:43:04,975 --> 00:43:06,499 이 또한 상당히 놀랍습니다. 424 00:43:06,499 --> 00:43:09,631 두 사람이 서핑보드를 들고 해변을 걷고있습니다. "Two people walking on the beach with surfbards" 425 00:43:09,631 --> 00:43:16,635 이 모델은 상당히 파워풀하고 이미지를 묘사하기 위해 비교적 복잡한 captions도 만들어낼 수 있습니다. 426 00:43:16,635 --> 00:43:19,808 하지만 그렇긴해도 모델이 아주 완벽하진 않습니다. 427 00:43:19,808 --> 00:43:24,319 전부다 마법같은 일만 일어나는 것은 아닙니다. 이 모델도 다른 Machine learning 모델들 처럼 428 00:43:24,319 --> 00:43:28,830 Train time에 보지 못한 데이터에 대해서는 엄청 잘 동작하지는 않습니다. 429 00:43:28,830 --> 00:43:33,317 가령, 여자가 손에 고양이를 들고 있습니다. "A woman is holding a cat in her hand" 430 00:43:33,317 --> 00:43:35,421 하지만 이미지에 고양이는 없습니다. 431 00:43:35,421 --> 00:43:41,359 하지만 여자가 모피 코트를 입고있습니다. 아마도 모델이 모피 코트의 텍스쳐를 고양이로 보고 있는 것 같습니다. 432 00:43:41,359 --> 00:43:44,379 여자가 해변에서 서핑보드를 들고있습니다. "A Woman standing on a beach holding a surfboard" 433 00:43:44,379 --> 00:43:47,892 하지만 분명 이 사람은 서핑보드를 들고있지 않습니다. 물구나무서기를 하고 있죠 434 00:43:47,892 --> 00:43:51,820 모델이 물구나무서기를 하고있다는 사실을 놓쳤습니다. 435 00:43:51,820 --> 00:43:58,238 그리고 여기 나뭇가지에 쳐있는 거미줄 사진이 있습니다. 436 00:43:58,238 --> 00:44:00,382 하지만 모델은 나뭇가지에 새가 앉아있다고 생각했습니다. "A bird is perched on a tree branch" 437 00:44:00,382 --> 00:44:05,139 모델은 거미에 관한 것들을 완전히 놓쳤습니다. 하지만 이 모델은 Train time에 거미를 보지 못했습니다. 438 00:44:05,139 --> 00:44:08,217 Train time에는 새가 나뭇가지에 않는다는 사실만 배웠을 뿐입니다. 439 00:44:08,217 --> 00:44:10,152 따라서 납득이 가는 실수하고 볼 수 있습니다. 440 00:44:10,152 --> 00:44:14,338 그리고 여기 밑에 보시면 모델은 이 사람이 공을 던지는 중인지 받는 중인지 구분하지 못합니다. 441 00:44:14,338 --> 00:44:17,709 하지만 어찌됐든 야구선수와 야구공이 어떤 연관이 있음은 모델이 알고 있습니다. 442 00:44:17,709 --> 00:44:20,441 다시한번 말씀드리지만 이 모델은 완벽하지 않습니다. 443 00:44:20,441 --> 00:44:25,109 Train data와 유사한 이미지를 던져주면 꾀나 잘 동작합니다. 444 00:44:25,109 --> 00:44:29,188 하지만 그 이상 일반적인 문제를 풀기는 조금 어렵습니다. 445 00:44:29,188 --> 00:44:34,152 조금 더 진보된 모델이 있습니다. Attention 이라는 모델입니다. 446 00:44:34,152 --> 00:44:41,036 이 모델은 Caption을 생성할 때 이미지의 다양한 부분을 집중해서(attention) 볼 수 있습니다. 447 00:44:41,036 --> 00:44:44,670 이번 시간에는 Attention 모델을 깊게 다루지는 않겠습니다. 448 00:44:44,670 --> 00:44:48,925 어떻게 동작하는지 간단하게 말씀드리자면 우선 CNN이 있습니다. 449 00:44:48,925 --> 00:44:59,954 CNN로 벡터 하나를 만드는게 아니라 각 벡터가 공간정보를 가지고 있는 grid of vector를 만들어냅니다.(LxD) 450 00:44:59,954 --> 00:45:06,618 Forward pass시에 매 스텝 vocabulary에서 샘플링을 할 때 451 00:45:06,618 --> 00:45:11,263 모델이 이미지에서 보고싶은 위치에 대한 분포 또한 만들어냅니다. 452 00:45:11,263 --> 00:45:18,276 이미지의 각 위치에 대한 분포는 Train time에 모델이 어느 위치를 봐야하는지에 대한 attention이라 할 수 있습니다. 453 00:45:18,276 --> 00:45:23,155 첫 번째 hidden state(h0)는 이미지의 위치에 대한 분포를 계산합니다. 454 00:45:23,155 --> 00:45:31,372 이 분포(a1)를 다시 벡터 집합(LxD Feature)과 연산하여 이미지 attention(z1)을 생성합니다. 455 00:45:31,372 --> 00:45:36,508 이 요약된 벡터(z1)는 Neural network의 다음 스텝의 입력으로 들어갑니다. 456 00:45:36,508 --> 00:45:38,278 그리고 두 개의 출력이 생성됩니다. (a2, d1) 457 00:45:38,278 --> 00:45:43,714 하나는 vocabulary의 각 단어들의 분포입니다(d1). 그리고 다른 하나(a2)는 이미지 위치에 대한 분포입니다. 458 00:45:43,714 --> 00:45:49,160 이 과정을 반복하면 매 스텝마다 값 두개(a, d)가 계속 만들어집니다. 459 00:45:50,296 --> 00:45:58,298 Train을 끝마치면, 모델이 caption을 생성하기 위해서 이미지의 attention을 이동시키는 모습을 볼 수 있습니다. 460 00:45:58,298 --> 00:46:04,436 가령 여기 만들어진 caption은 "A bird flying over a body of water." 입니다. 461 00:46:04,436 --> 00:46:12,473 caption을 만들 때 마다 이미지 내에 다양한 곳들에 attention을 주는 것을 볼 수 있습니다. 462 00:46:14,112 --> 00:46:19,147 사실 여기에는 hard/soft attention의 개념이 있습니다만, 너무 깊게 들어가진 않겠습니다. 463 00:46:19,147 --> 00:46:26,614 soft attention의 경우에는 "모든 특징"과 "모든 이미지 위치"간의 weighted combination을 취하는 경우입니다. 464 00:46:26,614 --> 00:46:34,259 반면 hard attention의 경우에는 모델이 각 타임 스텝마다 단 한곳만 보도록 강제한 경우입니다. 465 00:46:34,259 --> 00:46:38,277 hard attention의 경우에 이미지 위치를 딱 하나만 정해야 하는데, 사실상 하나만 정하기 까다롭습니다. 466 00:46:38,277 --> 00:46:46,247 따라서 Hard attention을 학습시키려면 기본 backprob 보다는 조금 더 fanier한 방법을 써야만 합니다. 467 00:46:46,247 --> 00:46:51,498 이에 관련된 것들은 다음에 reinforcement learning 시간에 더 다루겠습니다. 468 00:46:51,498 --> 00:46:57,415 Attention Model을 학습시키고 나서 Caption을 생성해보면 469 00:46:57,415 --> 00:47:04,067 실제로 모델이 Caption을 생성할 때 의미있는 부분에 attention을 집중한다는 것을 알 수 있습니다. 470 00:47:04,067 --> 00:47:08,413 여자가 공원에서 원반을 던지고 있습니다. 에서 "A woman is throwing a frisbee in a park" 471 00:47:08,413 --> 00:47:14,516 Attention mask를 살펴보면. 모델이 "원반(frisbee)" 라는 단어를 생성할 때 472 00:47:14,516 --> 00:47:18,976 이미지에서도 실제 원반이 위치하는 곳을 정확하게 attention하는 것을 알 수 있습니다. 473 00:47:18,976 --> 00:47:24,542 엄청 대단합니다. 우리는 모델에게 매 스텝 어디를 보라고 말해준 적이 없습니다. 474 00:47:24,542 --> 00:47:27,955 모델 스스로가 Train time에 알아냈습니다. 475 00:47:27,955 --> 00:47:32,721 모델이 그쪽(원반) 영역에 집중하는 것이 올바른 일이라는 것을 스스로 알아낸 것입니다. 476 00:47:32,721 --> 00:47:34,610 모델 전체가 미분가능하기 때문에 477 00:47:34,610 --> 00:47:42,541 soft attention 또한 backprob이 가능합니다. 따라서 이 모든 것들은 train time에서 나온 것들입니다. 478 00:47:42,541 --> 00:47:45,297 아주 대단합니다. 479 00:47:45,297 --> 00:47:51,565 RNN + Attention 조합은 Image captioning 뿐만 아니라 더 다양한 것들을 할 수 있습니다. 480 00:47:51,565 --> 00:47:54,691 가령 Visual Question Answering(VQA) 같이 말이죠. 481 00:47:54,691 --> 00:48:04,010 이 문제에서는 입력이 두 가지 입니다. 하나는 이미지이고 다른 하나는 이미지에 관련된 질문입니다. 482 00:48:04,010 --> 00:48:10,163 왼쪽과 같은 이미지에 다음과 같은 질문을 할 수 있을 것입니다. Q: 트럭에 그려져 있는 멸종위기 동물은 무엇입니까? 483 00:48:10,163 --> 00:48:19,027 모델은 네개의 보기 중에서 정답을 맞춰야 합니다. 484 00:48:19,027 --> 00:48:24,774 이 모델 또한 RNN과 CNN으로 만들 수 있습니다. 485 00:48:24,774 --> 00:48:29,701 이 경우에는 "many to one" 의 경우입니다. 486 00:48:29,701 --> 00:48:33,566 모델은 자연어 문장(질문)을 입력으로 받아야 합니다. 487 00:48:33,566 --> 00:48:40,111 이는 RNN을 통해 구현할 수 있습니다. RNN이 질문을 vector로 요약합니다. 488 00:48:40,111 --> 00:48:43,928 그리고 이미지 요약을 위해서는 CNN이 필요합니다. 489 00:48:43,928 --> 00:48:51,645 CNN/RNN에서 나온 벡터를 조합하면 질문에 대한 분포를 예측할 수 있을 것입니다. 490 00:48:51,645 --> 00:48:59,175 그리고 간혹 VQA 문제를 풀기 위해서 soft special attenion 알고리즘을 적용하는 경우도 있습니다. 491 00:48:59,175 --> 00:49:07,062 이 예시를 보시면 모델이 정답을 결정하기 위해서 이미지에 대한 attention을 만들어내는 것을 볼 수 있습니다. 492 00:49:07,062 --> 00:49:09,062 질문있나요? 493 00:49:18,715 --> 00:49:20,878 질문은 "어떻게 서로 다른 입력을 조합하는지" 입니다. (CNN output과 RNN output을 어떻게 합치는지) 494 00:49:20,878 --> 00:49:25,998 어떻게 요약된(encoded) 질문 벡터와, 요약된 이미지 벡터를 조합하는지를 여쭤보시는 것인가요? 495 00:49:25,998 --> 00:49:30,395 질문은 "encoded image와 encoded question를 어떻게 조합할 수 있는지" 입니다. 496 00:49:30,395 --> 00:49:34,847 가장 쉬운 방법중 하나는 concat으로 붙혀서 FC-Layer의 입력으로 만드는 방법입니다. 497 00:49:34,847 --> 00:49:37,864 이 방법이 가장 흔한 방법이고. 가장 먼저 시도해볼 수 있는 방법입니다. 498 00:49:37,864 --> 00:49:44,389 하지만 간혹 사람들이 더 강력한 함수를 만들기 위해서 두 벤터간의 더 복잡한 조합을 만들어내는 경우도 있습니다. 499 00:49:44,389 --> 00:49:48,050 어찌됐든 Concat하는 방법도 맨 처음 시도해보기에는 나쁘지 않은 방법입니다. 500 00:49:49,426 --> 00:49:55,084 지금까지 RNN을 활용한 다양한 예제들을 살펴보았습니다. 이 방법들 모두 대단한 방법들입니다. 501 00:49:55,084 --> 00:50:04,072 왜냐하면 RNN을 이용하면 CV와 NLP 문제를 조합시키는 복잡한 문제들을 풀 수 있기 때문입니다. 502 00:50:04,072 --> 00:50:08,870 이 복잡한 과정들은 레고 블럭들을 쌓는 것으로 볼 수 있습니다. 503 00:50:08,870 --> 00:50:16,736 가령 Image Captiong이나 VQA 같은 모델들은 여러 모듈(RNN,CNN)을 비교적 단순한 방법으로도 구현할 수 있습니다. 504 00:50:18,708 --> 00:50:26,274 또 한 가지 말씀드리고 싶은 것은, 지금까지는 단일 RNN 레이어를 사용했습니다. hidden state가 하나 뿐이었습니다. 505 00:50:26,274 --> 00:50:32,581 하지만 여러분이 자주 보게될 모델들은 Multi-layer RNN입니다. 506 00:50:32,581 --> 00:50:44,554 3-Layer RNN이 있습니다. 입력이 첫 번째 RNN으로 들어가서 첫 번째 hidden state를 만들어냅니다. 507 00:50:44,554 --> 00:50:50,468 RNN 하나를 돌리면 hidden states 스퀀스가 생깁니다. (밑에서 두 번째 행) 508 00:50:50,468 --> 00:50:56,474 이렇게 만들어진 hidden state 시퀀스를 다른 RNN의 입력으로 넣어줄 수 있습니다. 509 00:50:56,474 --> 00:51:01,577 그러면 두 번째 RNN layer가 만들어내는 또 다른 hidden states 시퀀스가 생겨납니다. (밑에서 세 번째) 510 00:51:01,577 --> 00:51:04,181 이런 식으로 RNN layer를 쌓아올릴 수 있을 것입니다. 511 00:51:04,181 --> 00:51:09,398 이렇게 하는 이유는 모델이 깊어질수록 다양한 문제들에서 성능이 더 좋아지기 때문입니다. 512 00:51:09,398 --> 00:51:18,215 이 법칙(더 깊게 쌓는 방법)이 RNN에서도 적용됩니다. 많은 경우에 3~4 layer RNN을 사용합니다. 513 00:51:18,215 --> 00:51:22,086 하지만 보통은 엄청나게 싶은 RNN모델을 사용하지는 않습니다. 514 00:51:22,086 --> 00:51:29,327 일반적으로는 2,3,4 layer RNN이 적절합니다. 515 00:51:29,327 --> 00:51:38,222 RNN을 사용할 때 문제점이 있습니다. 이는 아주 흥미롭고 중요한 주제입니다. 516 00:51:38,222 --> 00:51:43,229 RNN을 학습시킬 때 어떤 일이 생기는지 아주 신중히 생각해 봐야 합니다. 517 00:51:43,229 --> 00:51:47,447 여기 지금까지 우리가 봐왔던 일반적인(vanilla) RNN Cell이 있습니다. 518 00:51:47,447 --> 00:51:55,307 입력은 "현재 입력, x_t" 와 "이전 hidden state h_t-1" 입니다. 그리고 이 두 입력을 쌓습니다(stack). 519 00:51:55,307 --> 00:52:05,783 이렇게 두 입력을 쌓고 가중치 행렬 W와 행렬 곱 연산을 하고 tanh 를 씌워서 다음 hidden state(h_t)를 만듭니다. 520 00:52:05,783 --> 00:52:10,131 Vanilla RNN의 기본 수식입니다. 521 00:52:10,131 --> 00:52:17,738 그러면 이 아키텍쳐는 backward pass에 그레디언트를 계산하는 과정에서 어떤 일이 발생할까요? 522 00:52:17,738 --> 00:52:27,477 우선 Backward pass 시 h_t에 대한 loss의 미분값을 얻습니다. 523 00:52:28,568 --> 00:52:34,632 그 다음 Loss에 대한 h_t-1의 미분값을 계산하게 됩니다. 524 00:52:34,632 --> 00:52:39,881 backward pass의 전체과정은 여기 보이시는 빨간색 통로를 따르게 됩니다. 525 00:52:39,881 --> 00:52:45,958 우선 그레이언트가 tanh gate를 타고 흘러갑니다. 그 다음 "Mat mul gate" 를 통과합니다. 526 00:52:45,958 --> 00:52:54,711 여러분이 과제로 구현해 보았듯이 Mat mul gate의 backprop은 527 00:52:54,711 --> 00:52:58,457 결국 이 transpose(가중치 행렬) 을 곱하게 됩니다. 528 00:52:58,457 --> 00:53:08,024 이는 매번 vanilla RNN cells을 하나 통과할 때 마다 가중치 행렬의 일부를 곱하게 된다는 것을 의미합니다. 529 00:53:09,110 --> 00:53:16,599 RNN의 특성 상 RNN이 여러 시퀀스의 Cell을 쌓아 올리는 사실을 고려하면 530 00:53:16,599 --> 00:53:20,921 그레디언트가 RNN 모델의 Layers 시퀀스를 통해 어떤 방식으로 전달되는지 생각해 볼 수 있습니다. 531 00:53:20,921 --> 00:53:23,770 수상한 낌새가 보이기 시작합니다. 532 00:53:23,770 --> 00:53:30,810 가령 우리가 h_0에 대한 그레이언트를 구하고자 한다면 결국에는 모든 RNN Cells을 거쳐야 합니다. 533 00:53:30,810 --> 00:53:35,641 cell 하나를 통과할 때 마다 각 Cell의 행렬 W transpose factors가 관여합니다. 534 00:53:35,641 --> 00:53:44,967 다시 말해 h_0 의 그레디언트를 계산하는 식을 써보면 아주 많은 가중치 행렬들이 개입하며, 이는 안좋습니다. 535 00:53:44,967 --> 00:53:50,138 우선 가중치를 행렬이라고 생각하지 말고 스칼라로 생각해봅시다. 536 00:53:50,138 --> 00:53:54,563 우리이게 스칼라 값들이 있고 이 값들을 계속해서 곱한다고 했을 때 537 00:53:54,563 --> 00:54:00,269 여기 예제처럼 4개의 예제 뿐만 아니라 수백 개의 스텝이 있는 경우라면 538 00:54:00,269 --> 00:54:03,835 값들을 수백 번 곱해줘야 합니다. 아주 안좋습니다. 539 00:54:03,835 --> 00:54:14,069 만약 곱해지는 값이 1보다 큰 경우라면 점점 값이 커질 것이고 1보다 작은 경우라면 점점 작아져서 0이 될 것입니다. 540 00:54:14,069 --> 00:54:18,186 이 두 상황이 일어나지 않으려면 곱해지는 값이 1인 경우밖에 없습니다. 541 00:54:18,186 --> 00:54:20,911 실제로 1이 되기는 상당히 드뭅니다. 542 00:54:20,911 --> 00:54:25,229 스칼라에서의 이 intuition은 행렬에서도 동일하게 적용됩니다. 543 00:54:25,229 --> 00:54:32,071 가령 행렬의 특이값(singular value)이 엄청나게 큰 경우를 생각해 볼 수 있습니다. 544 00:54:32,071 --> 00:54:46,079 singular value가 엄청 큰 행렬을 계속 곱하는 경우에도 역시 h_0의 그레디언트는 아주 커지게됩니다. 545 00:54:46,079 --> 00:54:48,947 이를 "exploding gradient problem" 라고 합니다. 546 00:54:48,947 --> 00:54:55,061 backprop시 레이어가 깊어질수록 그레디언트가 기하급수적으로 증가하는 현상입니다. 547 00:54:55,061 --> 00:55:05,349 행렬의 특이값이 1보다 작은 경우라면 정 반대의 현상이 발생합니다. 이제는 기하급수적으로 그레디언트가 작아집니다. 548 00:55:05,349 --> 00:55:08,863 이를 "vanishing gradient problem" 이라고 합니다. 549 00:55:08,863 --> 00:55:14,208 그래서 사람들은 "gradient clipping" 이라는 기법을 사용하곤 합니다. 550 00:55:14,208 --> 00:55:19,713 "gradient clipping" 은 휴리스틱한 기법중 하나입니다. 그레디언트를 계산하고 551 00:55:19,713 --> 00:55:27,955 그레디언트의 L2 norm이 임계값보다 큰 경우 그레디언트가 최대 임계값을 넘지 못하도록 조정해줍니다. 552 00:55:27,955 --> 00:55:32,645 이 방법은 그닥 좋은 방법은 아니지만, 실제로는 많은 사람들이 RNN 학습에 이 방법을 활용합니다. 553 00:55:32,645 --> 00:55:39,034 exploding gradient problem을 해결하기에는 비교적 유용한 방법이긴 합니다. 554 00:55:39,034 --> 00:55:46,207 하지만 vanishing gradient problem를 다루려면 조금더 복잡한 RNN 아키텍쳐가 필요합니다. 555 00:55:46,207 --> 00:55:53,524 이는 LSTM에 관한 것입니다. LSTM은 Long Short Term Memory라는 뜻입니다. 556 00:55:53,524 --> 00:55:58,316 LSTM은 RNN의 fancier 버전입니다. 557 00:55:58,316 --> 00:56:03,330 LSTM은 vanishing & exploding gradients 문제를 완화시키기 위해서 디자인되었습니다. 558 00:56:03,330 --> 00:56:10,193 "gradient clipping" 같은 hack 을 쓰지 말고, 그레디언트가 잘 전달되도록 아키텍쳐 자체를 디자인한 경우입니다. 559 00:56:10,193 --> 00:56:16,556 기존에 배웠던 fancier CNN 아키텍쳐들과 유사한 느낌입니다. 560 00:56:16,556 --> 00:56:20,807 사실 LSTM은 1997년도에 나왔습니다. 561 00:56:20,807 --> 00:56:24,073 LSTM 이라는 아이디어 자체를 꽤 오랫동안 존재했습니다. 562 00:56:24,073 --> 00:56:28,852 사람들은 90년대에 이미 LSTM을 연구하고 있었고. 시대를 앞서갔던 연구라고 할 수 있습니다. 563 00:56:28,852 --> 00:56:32,475 20년이 지난 오늘날 LSTM은 어디서나 사용됩니다. 564 00:56:33,864 --> 00:56:37,921 LSTM은 아주 재밌게 생겼습니다. 565 00:56:37,921 --> 00:56:46,397 vanilla RNN은 hidden state가 있었습니다. 그리고 매 스텝 재귀적인 방법으로 hidden state를 업데이트했습니다. 566 00:56:46,397 --> 00:56:51,462 LSTM에는 한 Cell 당 두 개의 Hidden state가 있습니다. 567 00:56:51,462 --> 00:56:59,305 하나는 h_t 입니다. vanilla RNN에 있었던 hidden state(h_t)와 유사한 개념입니다. 568 00:56:59,305 --> 00:57:03,604 하지만 LSTM의 경우 "Cell state" 인 c_t라는 두 번째 벡터가 있습니다. 569 00:57:03,604 --> 00:57:12,240 Cell state, c_t 는 LSTM 내부에만 존재하며 밖에 노출되지 않는 변수입니다. 570 00:57:12,240 --> 00:57:15,260 LSTM의 Updata 식을 살펴봅시다. 571 00:57:15,260 --> 00:57:20,803 LSTM도 두 개의 입력을 받습니다.(h_t-1, x_t) 572 00:57:20,803 --> 00:57:25,485 그리고 4개의 gates를 계산합니다. i, f, o, 그리고 g 입니다. 573 00:57:25,485 --> 00:57:33,802 이 gates를 cell states, c_t를 업데이트하는데 이용합니다. 그리고 c_t로 다음 스텝의 hidden state를 업데이트합니다. 574 00:57:36,704 --> 00:57:44,014 LSTM는 아주 흥미롭게 생겼습니다. 앞으로 몇 장의 슬라이드는 LSTM이 어떻게, 왜 동작하는지 살펴보겠습니다. 575 00:57:44,014 --> 00:57:47,731 vanishing or exploding gradients의 관점에서 말이죠. 576 00:57:47,731 --> 00:57:57,213 우선 LSTM에서는 이전 hidden state인 h_t와 현재의 입력인 x_t를 입력으로 받습니다. 577 00:57:57,213 --> 00:57:58,611 vanilla RNN와 동일합니다. 578 00:57:58,611 --> 00:58:08,663 vanilla RNN의 경우에 두 입력(h_t-1, x_t)를 Cancat하고 행렬곱 연산으로 hidden state를 직접 구했습니다. 579 00:58:08,663 --> 00:58:15,315 LSTM의 경우는 조금 다릅니다. 이전 hidden state와 입력을 받아서 쌓아 놓습니다. 580 00:58:15,315 --> 00:58:21,926 그리고 네 개의 gates의 값을 계산하기 위한 커다한 가중치 행렬을 곱해줍니다. 581 00:58:21,926 --> 00:58:24,391 각 gates 출력은 hidden state의 크기와 동일합니다. 582 00:58:24,391 --> 00:58:30,808 물론 간혹 각 gate의 가중치 행렬의 크기를 다양한 방법으로 디자인할 수도 있습니다. 583 00:58:30,808 --> 00:58:33,160 어떤 사람들은 모든 값들을 조합해서 하나의 큰 가중치 행렬로 만들기도 합니다. 584 00:58:33,160 --> 00:58:34,677 하지만 여러 방법의 기본 아이디어는 모두 같습니다. 585 00:58:34,677 --> 00:58:40,288 기본적으로는, h_t-1과 x_t를 입력으로 받고 gates 4개를 계산해야 합니다. 586 00:58:40,288 --> 00:58:47,768 gates 4개는 [i, f, o, g]인데. 기억하기 쉽게 "ifog" 라고 부르기도 합니다. 587 00:58:47,768 --> 00:58:53,655 I 는 input gate입니다. I는 Cell에서의 입력 x_t에 대한 가중치입니다. 588 00:58:53,655 --> 00:59:00,194 F는 forget gate입니다. F는 이전 스텝의 Cell의 정보를 얼마가 망강(forget) 할지에 대한 가중치입니다. 589 00:59:00,194 --> 00:59:04,653 O는 Output gate입니다. O는 Cell state, c_t를 얼마나 밖에 드러내 보일지에 대한 가중치입니다. 590 00:59:04,653 --> 00:59:10,130 G는 그닥 좋은 이름은 아니지만 저는 "gate gate" 라고 부릅니다. 591 00:59:10,130 --> 00:59:14,626 G는 input cell을 얼마나 포함시킬지 결정하는 가중치입니다. 592 00:59:14,626 --> 00:59:19,665 중요한 점 중 하나는, 각 gate에서 사용하는 nin-linearity가 각양각색 이라는 점입니다. 593 00:59:21,724 --> 00:59:25,047 input/forget/output gate의 경우는 sigmoid를 샤용합니다. 594 00:59:25,047 --> 00:59:28,571 gate의 값이 0~1 사이라는 의미입니다. 595 00:59:28,571 --> 00:59:34,316 반면 gate gate는 tanh를 사용합니다. 따라서 gate gate는 -1 ~ +1 의 값을 갖습니다. 596 00:59:34,316 --> 00:59:41,725 이 부분이 조금 이상해 보일 수도 있지만, 사실은 더 이치에 맞습니다. 가령 gate값이 binary라고 생각해 봅시다. 597 00:59:41,725 --> 00:59:44,744 값이 binary(0,1 or -1,+1) 이라면 어떤 일이 일어날까요? 598 00:59:46,033 --> 00:59:53,926 밑에 수식을 살펴봅시다. 599 00:59:53,926 --> 01:00:00,350 이전 스텝의 Cell states(C_t-1)는 forget gate와 element-wise multiplication 합니다. 600 01:00:00,350 --> 01:00:03,861 결과 vector는 (f*c_t-1) 0또는 1일 것입니다. 601 01:00:03,861 --> 01:00:10,644 따라서 forget gate = 0인 element는 이전 cell state를 잊습니다. 602 01:00:10,644 --> 01:00:14,935 반면 forget gate = 1이면 cell state의 element를 계속 기억합니다. 603 01:00:14,935 --> 01:00:19,767 지금까지 살펴본 forget gate는 이전 cell state의 gate on/off 를 결정했습니다. 604 01:00:19,767 --> 01:00:24,814 이제 두 번째 수식을 살펴보겠습니다. element-wise product인 i * g 입니다. 605 01:00:24,814 --> 01:00:28,824 벡터 i의 경우에는 시그모이드에서 나온 녀석이므로 0 또는 1입니다. 606 01:00:28,824 --> 01:00:35,728 cell state의 각 element에 대해서, 이 cell state를 사용하고 싶으면 1 이 됩니다. 607 01:00:35,728 --> 01:00:41,719 반면 쓰고싶지 않으면 i = 0 이 될 것입니다. 608 01:00:41,719 --> 01:00:46,031 gate gate는 tanh 출력이기 때문에 값이 -1 또는 +1 입니다. 609 01:00:46,031 --> 01:00:54,022 c_t 는 현재 스텝에서 사용될 수 있는 "후보" 라고 할 수 있습니다. 610 01:00:54,022 --> 01:01:02,499 Cell State(c_t)를 계산하는 전체 수식을 살펴봅시다.이 수식은 두 개의 독립적인 scaler 값(f, i)에 의해 조정됩니다. 611 01:01:02,499 --> 01:01:05,230 각 값(f, i)은 1까지 증가하거나 감소합니다. 612 01:01:05,230 --> 01:01:11,028 c_t의 수식을 해석해보면, 우선 이전 cell state(c_t-1)을 계속 기억할지 말지를 결정합니다. (f * c_t-1) 613 01:01:11,028 --> 01:01:16,535 그런다음 각 스텝마다 1까지 cell state의 각 요소를 증가시키거나 감소시킬 수 있습니다. (i * g) 614 01:01:16,535 --> 01:01:25,708 즉 cell state의 각 요소는 scaler integer counters 처럼 값이 줄었다 늘었다 하는 것으로 볼 수 있습니다. 615 01:01:25,708 --> 01:01:36,513 Cell state를 계산했다면 이제는 hidden state를 업데이트 할 차례입니다. h_t는 실제 밖으로 보여지는 값입니다. 616 01:01:36,513 --> 01:01:43,353 그렇게 때문에 cell state는 counters의 개념으로 해석할 수 있습니다. 각 스텝마다 최대 1 또는 -1씩 세는 것이죠 617 01:01:43,353 --> 01:01:51,826 그리고 이 값은 tanh를 통과합니다. 그리고 최종적으로 output gate와 곱해집니다. 618 01:01:51,826 --> 01:01:57,597 그리고 output gate 또한 sigmoid에서 나온 값입니다. 따라서 0 ~ 1의 값을 가집니다. 619 01:01:57,597 --> 01:02:08,577 output gate는 각 스텝에서 다음 hidden sate를 계산할 때 cell state를 얼마나 노출시킬지를 결정합니다. 620 01:02:09,736 --> 01:02:17,132 대부분의 사람들이 자기들만 알아볼 수 있는 복잡한 LSTM 다이어그램을 그려놓고 남들에게 설명하려는 경향이 있습니다. 621 01:02:17,132 --> 01:02:18,882 그 중 이 다이어그램은 제가 만들었습니다. :D 622 01:02:20,380 --> 01:02:23,866 이 다이어그램을 보시면 LSTM cell이 어떤게 동작하는지 알 수 있습니다. 623 01:02:23,866 --> 01:02:31,266 우선 왼쪽을 보면 이전의 cell state(c_t-1)과 hidden state(h_t-1) 을 입력으로 받습니다. 현재 입력 x_t도 있죠 624 01:02:31,266 --> 01:02:37,346 우선 이전 hidden state (h_t-1)과 현재 입력 x_t를 쌓습니다. 625 01:02:37,346 --> 01:02:41,166 그리고 가중치 행렬 W를 곱해서 4 개의 gates를 만듭니다. 626 01:02:41,166 --> 01:02:44,836 Non-Linearity에 관해서는 이전 슬라이드에서 다뤘으므로 여기에서는 제외시켰습니다. 627 01:02:44,836 --> 01:02:48,143 그리고 forget gate를 이전 cell state(c_t-1)와 곱합니다. 628 01:02:48,143 --> 01:02:54,524 그리고 input/gate gate가 element wise로 곱한 후 cell state(c_t-1 *f)와 곱해서 다음 cell 을 만듭니다. 629 01:02:54,524 --> 01:03:01,366 c_t는 tanh를 거친 후 output gate와 곱해져서 다음 hidden state(h_t)를 만들어냅니다. 630 01:03:02,417 --> 01:03:03,250 질문있나요? 631 01:03:13,116 --> 01:03:17,878 (질문 내용 X) 아닙니다. 각 gate는 각 gate마다 곱해지는 가중치 행렬을 가지고 있습니다. 632 01:03:17,878 --> 01:03:26,415 우선 x와 h를 쌓으면 전체 h x 1 행렬이 됩니다. 633 01:03:26,415 --> 01:03:30,393 그리고 가중치 행렬의 크기는 4h x 2h 입니다. 634 01:03:30,393 --> 01:03:41,511 이 가중치 행렬은 행렬 4개를 합쳐 놓은 것이라고 보시면 됩니다. 각 4개의 행렬은 서로 가능 gate를 계산합니다. 635 01:03:42,404 --> 01:03:51,109 간혹 수식를 더 간단하게 쓰기 위해서 4개의 행렬을 그저 행렬 W로 표현하는 경우도 있습니다. 636 01:03:51,109 --> 01:03:56,067 가중치 행렬이 합쳐있어 보이긴 해도 결국은 4개의 가중치 행렬로 나누어져 있다고 보시면 됩니다. 637 01:03:57,080 --> 01:04:04,574 하지만 결국은 모두 두 개의 입력(x, h) 를 쌓고 행렬 곱 연산을 수행하는 것입니다. 638 01:04:04,574 --> 01:04:11,196 슬라이드의 그림을 살펴보겠습니다. LSTM의 backward pass는 어떨까요? 639 01:04:11,196 --> 01:04:18,999 앞서 vanilla RNN의 경우에는 backward pass에서 문제점이 있었습니다. 가중치 행렬 w가 계속해서 곱해지는 문제였죠. 640 01:04:18,999 --> 01:04:23,238 하지만 LSTM에서는 상황이 많이 달라졌습니다. 641 01:04:23,238 --> 01:04:29,952 LSTM에서 cell state의 gradient를 계산하는 backward 경로를 살펴보게 되면, 아주 괜찮아보입니다. 642 01:04:29,952 --> 01:04:33,320 자 그럼 cell state에서 내려오는 upsteam gradient를 살펴봅시다. 643 01:04:33,320 --> 01:04:37,737 우선 "addition operation"의 backprob이 있습니다. 644 01:04:37,737 --> 01:04:43,663 지난 강의에서 배웠듯이 "addition" 에서는 upstream gradient가 그저 두 갈래로 복사됩니다. 645 01:04:43,663 --> 01:04:50,435 따라서 "element wise multply" 로 직접 전달됩니다. 646 01:04:50,435 --> 01:04:56,455 따라서 그레디언트는 upsteam gradient와 forget gate의 element wise 곱입니다. 647 01:04:56,455 --> 01:05:07,171 결국 Cell state의 backprob은 그저 upstream gradient * forget gate 입니다. 648 01:05:07,171 --> 01:05:12,640 이 특성은 vanilla RNN에 비해 좋은점이 두 가지 있습니다. 649 01:05:12,640 --> 01:05:18,498 우선 forget gate와 곱해지는 연산이 matrix multiplication가 아닌 element-wise라는 점입니다. 650 01:05:18,498 --> 01:05:24,964 full matrix multiplication 보다는 element wise multiplication이 더 낫습니다. 651 01:05:24,964 --> 01:05:31,354 두 번째는 element wise multiplication을 통해 매 스텝 다른 값의 forget gate와 곱해질 수 있다는 점입니다. 652 01:05:31,354 --> 01:05:36,660 앞서 vanilla RNN의 경우에는 동일한 가중치 행렬(h_t)만을 계속 곱했습니다. 653 01:05:36,660 --> 01:05:40,563 이는 exploding/vanishing gradient문제를 일으켰습니다. 654 01:05:40,563 --> 01:05:45,161 반면 LSTM에서는 forget gate가 스텝마다 계속 변합니다. 655 01:05:45,161 --> 01:05:51,670 따라서 LSTM은 exploding/vanishing gradient 문제를 더 쉽게 해결할 수 있습니다. 656 01:05:51,670 --> 01:05:58,438 그리고 forget gate는 sigmoid에서 나온 값이므로 element wise multply가 0~1 사이의 값입니다. 657 01:05:58,438 --> 01:06:04,278 따라서 forget gate를 반복적으로 곱한다고 했을 때 더 좋은 수치적 특성을 보일 수 있습니다. 658 01:06:04,278 --> 01:06:14,273 그리고 또 한가지 명심해야 할 점은, vanilla RNN의 backward pass에서는 매 스탭 그래디언트가 tanh를 거쳐야 했습니다. 659 01:06:14,273 --> 01:06:24,110 LSTM에서도 hidden state h_t를 출력 y_t를 계산하는 데 사용합니다. 660 01:06:24,110 --> 01:06:33,024 가령 LSTM의 최종 hidden state h_t를 가장 첫 cell state(c_0)까지 backprob하는 것을 생각해보면 661 01:06:33,024 --> 01:06:42,044 RNN처럼 매 스탭마다 tanh를 거치는 것이 아니라 tamh를 단 한번만 거치면 됩니다. 662 01:06:42,044 --> 01:06:50,483 LSTM을 전체적인 모습을 그려보면, Cell state를 통한 backprob은 그레디언트를 위한 고속도로라고 볼 수 있습니다. 663 01:06:50,483 --> 01:06:59,172 그레디언트가 모델의 종단인 Loss에서 가장 처음 Cell State(C_0)까지 흘러가면서 방해를 덜받는 것이죠 664 01:06:59,172 --> 01:07:00,922 질문있나요? 665 01:07:02,901 --> 01:07:06,792 질문은 "궁극적으로 W를 업데이트해야 할텐데, W에 대한 그레디언트는 어떻게 되는지" 입니다. 666 01:07:06,792 --> 01:07:19,848 가중치 W에 대한 Local gradient는 해당 스텝에 해당하는 현재의 cell/Hidden state로부터 전달됩니다. 667 01:07:19,848 --> 01:07:29,587 Vanilla RNN의 경우에는 각 스텝의 가중치 행렬 W들이 서로 영향을 미쳤습니다. 668 01:07:29,587 --> 01:07:37,280 반면 LSTM의 경우에는, 가령 아주 긴 시퀀스가 있고 그레디언트가 맨 끝에서부터 전달되기 시작된다고 했을 때 669 01:07:37,280 --> 01:07:43,219 이 시퀀스의 backprob 과정에서 각 스텝마다 w에 대한 local gradient가 있을 것입니다. 670 01:07:43,219 --> 01:07:48,506 그리고 W의 local gradient는 Cel/Hiddenl state에서 흘러옵니다. 671 01:07:48,506 --> 01:07:52,751 LSTM의 경우 cell state c가 그레디언트를 잘 전달해주기 때문에 672 01:07:52,751 --> 01:07:59,804 w에 대한 local gradient도 훨씬 더 깔끔하게 전달됩니다. 673 01:08:01,627 --> 01:08:03,044 질문 있나요? 674 01:08:17,428 --> 01:08:22,088 질문은 "여전히 Non-linearities가 있으므로 (sigmoid) vanishing gradient 문제에 민감할 수 있는지" 입니다. 675 01:08:22,089 --> 01:08:34,103 그럴지도 모릅니다. 가령 forget gate의 경우 출력이 0~1 이니 항상 1보다 작으므로 그레디언트가 점점 감소할 수 있습니다. 676 01:08:34,103 --> 01:08:42,746 그래서 사람들이 많이 하는 Trick 으로 forget gate의 biases를 양수로 초기화시키는 방법이 있습니다. 677 01:08:42,746 --> 01:08:46,305 이 방법을 이용해서 학습 초기에 forget gate의 값이 1에 가깝도록 해줍니다. 678 01:08:46,305 --> 01:08:56,631 1에 가까운 값이기 때문에 적어도 학습 초기에는 그레디언트의 흐름이 비교적 원활할 것입니다. 679 01:08:56,631 --> 01:09:02,741 그리고 학습이 진행되면 forget gate의 biases가 적절한 자기 자리를 다시 찾아가겠죠 680 01:09:02,742 --> 01:09:09,182 LSTM에서도 vanishing gradient의 위험은 존재합니다. 다만 Vanilla RNN만큼 심하진 않습니다. 681 01:09:09,182 --> 01:09:12,126 덜 위험한 이유 중 하나는 매 스텝 f가 변하기 떄문이고 682 01:09:12,126 --> 01:09:19,126 두 번째 이유는 LSTM에서는 Full Mat-mul이 아닌 element-wise multiplication을 수행하기 때문입니다. 683 01:09:19,126 --> 01:09:23,048 LSTM을 유심히 들여다보면 RsetNet 스럽게 생겼습니다. 684 01:09:23,048 --> 01:09:28,069 ResNet의 Backward pass에서 identity connection이 아주 유용했습니다. 685 01:09:28,069 --> 01:09:32,303 Identity Mapping이 ResNet 그레디언트를 위한 고속도로 역할을 했습니다. 686 01:09:32,303 --> 01:09:34,924 LSTM도 동일한 intuition입니다. 687 01:09:34,924 --> 01:09:45,244 LSTM의 Cell state의 element-wise mult가 그레디언트를 위한 고속도로 역할을 하는 것이죠 688 01:09:46,343 --> 01:09:55,558 유사한 방법으로 "Highway Networks" 라는 논문도 있습니다. LSTM cell과 ResNet의 중간 버전입니다. 689 01:09:57,796 --> 01:10:01,165 사실은 Highway network는 ResNet보다 일찍 나온 논문입니다. 690 01:10:01,165 --> 01:10:08,804 highway network는 모든 레이어에서 "candidate activation"과 "gating function"을 계산합니다. 691 01:10:08,804 --> 01:10:17,017 gating function (g)는 현재 레이어의 이전 입력과 CNN 등에서 나온 candidate activation간의 보간 역할을 해줍니다. 692 01:10:17,017 --> 01:10:20,472 많은 아키텍쳐들(LSTM, ResNet)간의 유사성은 693 01:10:20,472 --> 01:10:27,688 사람들이 아주 깊은 CNN/RNN을 학습시키면서 얻은 영감에서 비롯됩니다. 이 지점에서 많은 교집합이 존재합니다. 694 01:10:27,688 --> 01:10:34,675 다시 말하면 실제로 아주 다양한 RNN 아키텍쳐의 변형된 버전들이 존재합니다. 695 01:10:34,675 --> 01:10:40,853 그 중 LSTM 다음으로 유명한 아키텍쳐는 GRU 입니다. Gated Recurrent Unit 이죠. 696 01:10:40,853 --> 01:10:45,701 업데이트 식은 보시는 바와 같습니다. LSTM과 유사하게 생겼습니다. 697 01:10:45,701 --> 01:10:53,828 Vanishing gradient 문제를 회피하기 위한 element-wise mult gate 등이 보이는군요 698 01:10:53,828 --> 01:10:59,734 그리고 또 "LSTM: A Search Space Odyssey" 라는 논문도 있습니다. 아주 독창적인 제목입니다. 699 01:10:59,734 --> 01:11:04,980 이 논문에서는 LSTM의 수식을 이리저리 바꾸고 실험을 합니다. 가령 non linearities를 바꿔봅니다. 700 01:11:04,980 --> 01:11:07,343 output gate에 꼭 tanh를 써야만 하는지 등을 실험했습니다. 701 01:11:07,343 --> 01:11:14,017 그들은 다양한 질문을 만들고 이에 답할 수 있는 여러가지 실험을 진행하였습니다. 702 01:11:14,017 --> 01:11:18,068 그리고 LSTM 모델을 조금씩 변형시켜보고 어떤 일이 발생하는지 실험하였습니다. 703 01:11:18,068 --> 01:11:24,521 결론은 전부 비슷비슷했다는 것입니다. 어떤 문제에서는 특정 모델이 더 잘 될수는 있겠지만. 결국은 다 비슷했습니다. 704 01:11:24,521 --> 01:11:32,148 하지만 그들이 시도한 어떠한 방법들도 "모든 문제들" 에서 original LSTM보다 엄청나게 좋지는 않았습니다. 705 01:11:32,148 --> 01:11:41,084 이는 LSTM 업데이트 수식이 뭔진 모르겠지만 어쨋든 유용하고. 각자 문제에 적용해볼만하는 것을 시사합니다. 706 01:11:41,084 --> 01:11:43,692 몇 해 전 Google에서도 아주 재미있는 논문이 나왔습니다. 707 01:11:43,692 --> 01:11:52,605 이들은 evolutionary search 기법을 이용해서 아주 많은 임의의 RNN 아키텍쳐를 실험합니다. 708 01:11:52,605 --> 01:12:00,860 이들은 임의로 업데이트 수식을 섞고 addition/multiplication non-linearities를 다양한 조합으로 섞습니다. 709 01:12:00,860 --> 01:12:08,570 Huge Google cluster 를 이용해서 다양한 방법들을 모조리 실험해 버립니다. 710 01:12:08,570 --> 01:12:15,446 하지만 결론은 같습니다. GRU와 LSTM 보다 엄청나게 좋은 모델을 찾아내지는 못했습니다. 711 01:12:15,446 --> 01:12:19,518 조금 변형된 모델이 특정 문제에는 조금 더 좋을수는 있었습니다. 반대로 안 좋을수도 있습니다. 712 01:12:19,518 --> 01:12:27,080 최종 결론으로 아셔야 할 점은 바로 LSTM과 GRU가 아무렇게나 만든 수식이 아니라는 것입니다. 713 01:12:27,080 --> 01:12:33,356 LSTM와 GRU는 Gradient Flow를 아주 적절하게 관리하며 추가된 gate는 아주 유용함은 사실입니다. 714 01:12:34,888 --> 01:12:40,103 오늘 내용을 요약 하자면 RNN은 완전 멋있습니다. RNN으로 다양한 새로운 문제에 도전해 볼 수 있습니다. 715 01:12:40,103 --> 01:12:43,431 떄로는 RNN은 vanishing/exploding gradient 문제에 민감할수도 있습니다. 716 01:12:43,431 --> 01:12:47,412 이 문제들은 weight clipping이나 다른 fancier한 아키텍쳐(LSTM, GRU)로 극복할 수 있었습니다. 717 01:12:47,412 --> 01:12:52,043 그리고 CNN/RNN 아키텍쳐 간에는 교집합이 아주 많았습니다. 718 01:12:52,043 --> 01:13:02,801 다음 시간은 중간고사합니다. 오늘 배운 RNN까지가 범위입니다. 모두 중간고사 화이팅입니다.